| 265 | } |
| 266 | |
| 267 | bool HRTFElevation::calculateKernelsForAzimuthElevation( |
| 268 | HRTFDatabaseInfo * info, int azimuth, int elevation, |
| 269 | std::shared_ptr<HRTFKernel> & kernelL, std::shared_ptr<HRTFKernel> & kernelR) |
| 270 | { |
| 271 | // Valid values for azimuth are 0 -> 345 in 15 degree increments. |
| 272 | // Valid values for elevation are -45 -> +90 in 15 degree increments. |
| 273 | |
| 274 | bool isAzimuthGood = azimuth >= 0 && azimuth <= 345 && (azimuth / 15) * 15 == azimuth; |
| 275 | ASSERT(isAzimuthGood); |
| 276 | if (!isAzimuthGood) return false; |
| 277 | |
| 278 | bool isElevationGood = elevation >= -45 && elevation <= 90 && (elevation / 15) * 15 == elevation; |
| 279 | ASSERT(isElevationGood); |
| 280 | if (!isElevationGood) return false; |
| 281 | |
| 282 | // Construct the resource name from the subject name, azimuth, and elevation, for example: |
| 283 | // "IRC_Composite_C_R0195_T015_P000" |
| 284 | int positiveElevation = elevation < 0 ? elevation + 360 : elevation; |
| 285 | |
| 286 | char tempStr[16]; |
| 287 | |
| 288 | // Located in $searchPath / [format] .wav |
| 289 | // @tofix - this assumes we want to open this path and read via libnyquist fopen. |
| 290 | // ... will need to change for Android. Maybe MakeBusFromInternalResource / along |
| 291 | // with a LoadInternalResources required by LabSound |
| 292 | sprintf(tempStr, "%03d_P%03d", azimuth, positiveElevation); |
| 293 | std::string resourceName = info->searchPath + "/" + "IRC_" + info->subjectName + "_C_R0195_T" + tempStr + ".wav"; |
| 294 | |
| 295 | std::shared_ptr<AudioBus> impulseResponse = lab::MakeBusFromFile(resourceName.c_str(), false); |
| 296 | |
| 297 | if (!impulseResponse) |
| 298 | { |
| 299 | LOG_ERROR("impulse not found %s (bad path?)", resourceName.c_str()); |
| 300 | return false; |
| 301 | } |
| 302 | |
| 303 | // The impulse files are 44.1k so we need to resample them if the graph is playing back at any other rate |
| 304 | if (info->sampleRate != 44100.0f) |
| 305 | { |
| 306 | std::unique_ptr<AudioBus> resampledImpulseResponse = AudioBus::createBySampleRateConverting(impulseResponse.get(), false, info->sampleRate); |
| 307 | impulseResponse = std::move(resampledImpulseResponse); |
| 308 | // LOG_VERBOSE("converting %s impulse to %f hz", resourceName.c_str(), info->sampleRate); |
| 309 | } |
| 310 | |
| 311 | // Check number of channels. For now these are fixed and known. |
| 312 | bool isBusGood = (impulseResponse->numberOfChannels() == Channels::Stereo); |
| 313 | |
| 314 | ASSERT(isBusGood); |
| 315 | if (!isBusGood) |
| 316 | { |
| 317 | return false; |
| 318 | } |
| 319 | |
| 320 | AudioChannel * leftEarImpulseResponse = impulseResponse->channelByType(Channel::Left); |
| 321 | AudioChannel * rightEarImpulseResponse = impulseResponse->channelByType(Channel::Right); |
| 322 | |
| 323 | // Note that depending on the fftSize returned by the panner, we may be truncating the impulse response we just loaded in. |
| 324 | const int fftSize = HRTFPanner::fftSizeForSampleRate(info->sampleRate); |
nothing calls this directly
no test coverage detected