Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: Source/core/platform/audio/HRTFElevation.cpp

Issue 14304002: Support concatenated spatialization data (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Rebase Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Source/WebKit/chromium/WebKit.grd ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2010 Google Inc. All rights reserved. 2 * Copyright (C) 2010 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
55 // Total number of components of an HRTF database. 55 // Total number of components of an HRTF database.
56 const size_t TotalNumberOfResponses = 240; 56 const size_t TotalNumberOfResponses = 240;
57 57
58 // Number of frames in an individual impulse response. 58 // Number of frames in an individual impulse response.
59 const size_t ResponseFrameSize = 256; 59 const size_t ResponseFrameSize = 256;
60 60
61 // Sample-rate of the spatialization impulse responses as stored in the resource file. 61 // Sample-rate of the spatialization impulse responses as stored in the resource file.
62 // The impulse responses may be resampled to a different sample-rate (depending on the audio hardware) when they are loaded. 62 // The impulse responses may be resampled to a different sample-rate (depending on the audio hardware) when they are loaded.
63 const float ResponseSampleRate = 44100; 63 const float ResponseSampleRate = 44100;
64 64
65 // Lazily load a concatenated HRTF database for given subject and store it in a
66 // local hash table to ensure quick efficient future retrievals.
67 static AudioBus* getConcatenatedImpulseResponsesForSubject(const String& subject Name)
68 {
69 typedef HashMap<String, AudioBus*> AudioBusMap;
70 DEFINE_STATIC_LOCAL(AudioBusMap, audioBusMap, ());
71
72 AudioBus* bus;
73 AudioBusMap::iterator iterator = audioBusMap.find(subjectName);
74 if (iterator == audioBusMap.end()) {
75 OwnPtr<AudioBus> concatenatedImpulseResponses = AudioBus::loadPlatformRe source(subjectName.utf8().data(), ResponseSampleRate);
76 ASSERT(concatenatedImpulseResponses);
77 if (!concatenatedImpulseResponses)
78 return 0;
79
80 bus = concatenatedImpulseResponses.leakPtr();
81 audioBusMap.set(subjectName, bus);
82 } else
83 bus = iterator->value;
84
85 size_t responseLength = bus->length();
86 size_t expectedLength = static_cast<size_t>(TotalNumberOfResponses * Respons eFrameSize);
87
88 // Check number of channels and length. For now these are fixed and known.
89 bool isBusGood = responseLength == expectedLength && bus->numberOfChannels() == 2;
90 ASSERT(isBusGood);
91 if (!isBusGood)
92 return 0;
93
94 return bus;
95 }
96
65 // Takes advantage of the symmetry and creates a composite version of the two me asured versions. For example, we have both azimuth 30 and -30 degrees 97 // Takes advantage of the symmetry and creates a composite version of the two me asured versions. For example, we have both azimuth 30 and -30 degrees
66 // where the roles of left and right ears are reversed with respect to each othe r. 98 // where the roles of left and right ears are reversed with respect to each othe r.
67 bool HRTFElevation::calculateSymmetricKernelsForAzimuthElevation(int azimuth, in t elevation, float sampleRate, const String& subjectName, 99 bool HRTFElevation::calculateSymmetricKernelsForAzimuthElevation(int azimuth, in t elevation, float sampleRate, const String& subjectName,
68 RefPtr<HRTFKern el>& kernelL, RefPtr<HRTFKernel>& kernelR) 100 RefPtr<HRTFKern el>& kernelL, RefPtr<HRTFKernel>& kernelR)
69 { 101 {
70 RefPtr<HRTFKernel> kernelL1; 102 RefPtr<HRTFKernel> kernelL1;
71 RefPtr<HRTFKernel> kernelR1; 103 RefPtr<HRTFKernel> kernelR1;
72 bool success = calculateKernelsForAzimuthElevation(azimuth, elevation, sampl eRate, subjectName, kernelL1, kernelR1); 104 bool success = calculateKernelsForAzimuthElevation(azimuth, elevation, sampl eRate, subjectName, kernelL1, kernelR1);
73 if (!success) 105 if (!success)
74 return false; 106 return false;
(...skipping 23 matching lines...) Expand all
98 bool isAzimuthGood = azimuth >= 0 && azimuth <= 345 && (azimuth / 15) * 15 = = azimuth; 130 bool isAzimuthGood = azimuth >= 0 && azimuth <= 345 && (azimuth / 15) * 15 = = azimuth;
99 ASSERT(isAzimuthGood); 131 ASSERT(isAzimuthGood);
100 if (!isAzimuthGood) 132 if (!isAzimuthGood)
101 return false; 133 return false;
102 134
103 bool isElevationGood = elevation >= -45 && elevation <= 90 && (elevation / 1 5) * 15 == elevation; 135 bool isElevationGood = elevation >= -45 && elevation <= 90 && (elevation / 1 5) * 15 == elevation;
104 ASSERT(isElevationGood); 136 ASSERT(isElevationGood);
105 if (!isElevationGood) 137 if (!isElevationGood)
106 return false; 138 return false;
107 139
108 // Construct the resource name from the subject name, azimuth, and elevation , for example: 140 int positiveElevation = elevation < 0 ? elevation + 360 : elevation;
109 // "IRC_Composite_C_R0195_T015_P000" 141
110 // Note: the passed in subjectName is not a string passed in via JavaScript or the web. 142 // Note: the passed in subjectName is not a string passed in via JavaScript or the web.
111 // It's passed in as an internal ASCII identifier and is an implementation d etail. 143 // It's passed in as an internal ASCII identifier and is an implementation d etail.
Chris Rogers 2013/04/23 19:51:44 This comment used to be just before line 140 and y
112 int positiveElevation = elevation < 0 ? elevation + 360 : elevation; 144 AudioBus* bus(getConcatenatedImpulseResponsesForSubject(subjectName));
113 145
114 String resourceName = String::format("IRC_%s_C_R0195_T%03d_P%03d", subjectNa me.utf8().data(), azimuth, positiveElevation); 146 if (!bus)
147 return false;
115 148
116 OwnPtr<AudioBus> impulseResponse(AudioBus::loadPlatformResource(resourceName .utf8().data(), sampleRate)); 149 int elevationIndex = positiveElevation / AzimuthSpacing;
150 if (positiveElevation > 90)
151 elevationIndex -= AzimuthSpacing;
117 152
118 ASSERT(impulseResponse.get()); 153 // The concatenated impulse response is a bus containing all
119 if (!impulseResponse.get()) 154 // the elevations per azimuth, for all azimuths by increasing
155 // order. So for a given azimuth and elevation we need to compute
156 // the index of the wanted audio frames in the concatenated table.
157 unsigned index = ((azimuth / AzimuthSpacing) * HRTFDatabase::NumberOfRawElev ations) + elevationIndex;
158 bool isIndexGood = index < TotalNumberOfResponses;
159 ASSERT(isIndexGood);
160 if (!isIndexGood)
120 return false; 161 return false;
121
122 size_t responseLength = impulseResponse->length();
123 size_t expectedLength = static_cast<size_t>(256 * (sampleRate / 44100.0));
124 162
125 // Check number of channels and length. For now these are fixed and known. 163 // Extract the individual impulse response from the concatenated
126 bool isBusGood = responseLength == expectedLength && impulseResponse->number OfChannels() == 2; 164 // responses and potentially sample-rate convert it to the desired
127 ASSERT(isBusGood); 165 // (hardware) sample-rate.
128 if (!isBusGood) 166 unsigned startFrame = index * ResponseFrameSize;
129 return false; 167 unsigned stopFrame = startFrame + ResponseFrameSize;
130 168 OwnPtr<AudioBus> preSampleRateConvertedResponse = AudioBus::createBufferFrom Range(bus, startFrame, stopFrame);
131 AudioChannel* leftEarImpulseResponse = impulseResponse->channelByType(AudioB us::ChannelLeft); 169 OwnPtr<AudioBus> response = AudioBus::createBySampleRateConverting(preSample RateConvertedResponse.get(), false, sampleRate);
132 AudioChannel* rightEarImpulseResponse = impulseResponse->channelByType(Audio Bus::ChannelRight); 170 AudioChannel* leftEarImpulseResponse = response->channel(AudioBus::ChannelLe ft);
171 AudioChannel* rightEarImpulseResponse = response->channel(AudioBus::ChannelR ight);
133 172
134 // Note that depending on the fftSize returned by the panner, we may be trun cating the impulse response we just loaded in. 173 // Note that depending on the fftSize returned by the panner, we may be trun cating the impulse response we just loaded in.
135 const size_t fftSize = HRTFPanner::fftSizeForSampleRate(sampleRate); 174 const size_t fftSize = HRTFPanner::fftSizeForSampleRate(sampleRate);
136 kernelL = HRTFKernel::create(leftEarImpulseResponse, fftSize, sampleRate); 175 kernelL = HRTFKernel::create(leftEarImpulseResponse, fftSize, sampleRate);
137 kernelR = HRTFKernel::create(rightEarImpulseResponse, fftSize, sampleRate); 176 kernelR = HRTFKernel::create(rightEarImpulseResponse, fftSize, sampleRate);
138 177
139 return true; 178 return true;
140 } 179 }
141 180
142 // The range of elevations for the IRCAM impulse responses varies depending on a zimuth, but the minimum elevation appears to always be -45. 181 // The range of elevations for the IRCAM impulse responses varies depending on a zimuth, but the minimum elevation appears to always be -45.
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 void HRTFElevation::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const 316 void HRTFElevation::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
278 { 317 {
279 MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::AudioShare dData); 318 MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::AudioShare dData);
280 info.addMember(m_kernelListL, "kernelListL"); 319 info.addMember(m_kernelListL, "kernelListL");
281 info.addMember(m_kernelListR, "kernelListR"); 320 info.addMember(m_kernelListR, "kernelListR");
282 } 321 }
283 322
284 } // namespace WebCore 323 } // namespace WebCore
285 324
286 #endif // ENABLE(WEB_AUDIO) 325 #endif // ENABLE(WEB_AUDIO)
OLDNEW
« no previous file with comments | « Source/WebKit/chromium/WebKit.grd ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698