Changeset 99934 in webkit


Ignore:
Timestamp:
Nov 11, 2011 12:40:02 AM (13 years ago)
Author:
Philippe Normand
Message:

HRTF Database consolidation
https://bugs.webkit.org/show_bug.cgi?id=69703

Reviewed by Kenneth Russell.

Access to the consolidated parts of the HRTF database by segmented
chunks. A concatenated Composite HRTF database is provided in
Composite.wav. Additionnally a new build step that concatenates
the platform/audio/resources/ files into one (sox can be used for
this) can be configured for specific ports.

  • platform/audio/HRTFDatabase.h:
  • platform/audio/HRTFElevation.cpp:

(WebCore::getConcatenatedImpulseResponsesForSubject):
(WebCore::HRTFElevation::calculateKernelsForAzimuthElevation):

  • platform/audio/resources/Composite.wav: Added.
Location:
trunk/Source/WebCore
Files:
1 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r99933 r99934  
     12011-10-28  Philippe Normand  <pnormand@igalia.com>
     2
     3        HRTF Database consolidation
     4        https://bugs.webkit.org/show_bug.cgi?id=69703
     5
     6        Reviewed by Kenneth Russell.
     7
     8        Access to the consolidated parts of the HRTF database by segmented
     9        chunks. A concatenated Composite HRTF database is provided in
     10        Composite.wav. Additionnally a new build step that concatenates
     11        the platform/audio/resources/ files into one (sox can be used for
     12        this) can be configured for specific ports.
     13
     14        * platform/audio/HRTFDatabase.h:
     15        * platform/audio/HRTFElevation.cpp:
     16        (WebCore::getConcatenatedImpulseResponsesForSubject):
     17        (WebCore::HRTFElevation::calculateKernelsForAzimuthElevation):
     18        * platform/audio/resources/Composite.wav: Added.
     19
    1202011-11-10  Pavel Feldman  <pfeldman@google.com>
    221
  • trunk/Source/WebCore/platform/audio/HRTFDatabase.h

    r96745 r99934  
    5959
    6060    float sampleRate() const { return m_sampleRate; }
    61    
     61
     62    // Number of elevations loaded from resource.
     63    static const unsigned NumberOfRawElevations;
     64
    6265private:
    6366    explicit HRTFDatabase(float sampleRate);
     
    6770    static const int MaxElevation;
    6871    static const unsigned RawElevationAngleSpacing;
    69    
    70     // Number of elevations loaded from resource.
    71     static const unsigned NumberOfRawElevations;
    7272
    7373    // Interpolates by this factor to get the total number of elevations from every elevation loaded from resource.
  • trunk/Source/WebCore/platform/audio/HRTFElevation.cpp

    r96745 r99934  
    5151const unsigned HRTFElevation::NumberOfTotalAzimuths = NumberOfRawAzimuths * InterpolationFactor;
    5252
     53// Total number of components of an HRTF database.
     54const size_t TotalNumberOfResponses = 240;
     55
     56// Number of frames in an individual impulse response.
     57const size_t ResponseFrameSize = 256;
     58
     59// Sample-rate of the spatialization impulse responses as stored in the resource file.
     60// The impulse responses may be resampled to a different sample-rate (depending on the audio hardware) when they are loaded.
     61const float ResponseSampleRate = 44100;
     62
     63#if PLATFORM(GTK)
     64#define USE_CONCATENATED_IMPULSE_RESPONSES
     65#endif
     66
     67#ifdef USE_CONCATENATED_IMPULSE_RESPONSES
     68// Lazily load a concatenated HRTF database for given subject and store it in a
     69// local hash table to ensure quick efficient future retrievals.
     70static AudioBus* getConcatenatedImpulseResponsesForSubject(const String& subjectName)
     71{
     72    typedef HashMap<String, AudioBus*> AudioBusMap;
     73    DEFINE_STATIC_LOCAL(AudioBusMap, audioBusMap, ());
     74
     75    AudioBus* bus;
     76    AudioBusMap::iterator iterator = audioBusMap.find(subjectName);
     77    if (iterator == audioBusMap.end()) {
     78        OwnPtr<AudioBus> concatenatedImpulseResponses = AudioBus::loadPlatformResource(subjectName.utf8().data(), ResponseSampleRate);
     79        bus = concatenatedImpulseResponses.leakPtr();
     80        audioBusMap.set(subjectName, bus);
     81    } else
     82        bus = iterator->second;
     83
     84    size_t responseLength = bus->length();
     85    size_t expectedLength = static_cast<size_t>(TotalNumberOfResponses * ResponseFrameSize);
     86
     87    // Check number of channels and length. For now these are fixed and known.
     88    bool isBusGood = responseLength == expectedLength && bus->numberOfChannels() == 2;
     89    ASSERT(isBusGood);
     90    if (!isBusGood)
     91        return 0;
     92
     93    return bus;
     94}
     95#endif
     96
    5397// Takes advantage of the symmetry and creates a composite version of the two measured versions.  For example, we have both azimuth 30 and -30 degrees
    5498// where the roles of left and right ears are reversed with respect to each other.
     
    99143    // It's passed in as an internal ASCII identifier and is an implementation detail.
    100144    int positiveElevation = elevation < 0 ? elevation + 360 : elevation;
     145
     146#ifdef USE_CONCATENATED_IMPULSE_RESPONSES
     147    AudioBus* bus(getConcatenatedImpulseResponsesForSubject(subjectName));
     148
     149    if (!bus)
     150        return false;
     151
     152    int elevationIndex = positiveElevation / AzimuthSpacing;
     153    if (positiveElevation > 90)
     154        elevationIndex -= AzimuthSpacing;
     155
     156    // The concatenated impulse response is a bus containing all
     157    // the elevations per azimuth, for all azimuths by increasing
     158    // order. So for a given azimuth and elevation we need to compute
     159    // the index of the wanted audio frames in the concatenated table.
     160    unsigned index = ((azimuth / AzimuthSpacing) * HRTFDatabase::NumberOfRawElevations) + elevationIndex;
     161    bool isIndexGood = index < TotalNumberOfResponses;
     162    ASSERT(isIndexGood);
     163    if (!isIndexGood)
     164        return false;
     165
     166    // Extract the individual impulse response from the concatenated
     167    // responses and potentially sample-rate convert it to the desired
     168    // (hardware) sample-rate.
     169    unsigned startFrame = index * ResponseFrameSize;
     170    unsigned stopFrame = startFrame + ResponseFrameSize;
     171    OwnPtr<AudioBus> preSampleRateConvertedResponse = AudioBus::createBufferFromRange(bus, startFrame, stopFrame);
     172    OwnPtr<AudioBus> response = AudioBus::createBySampleRateConverting(preSampleRateConvertedResponse.get(), false, sampleRate);
     173    AudioChannel* leftEarImpulseResponse = response->channel(AudioBus::ChannelLeft);
     174    AudioChannel* rightEarImpulseResponse = response->channel(AudioBus::ChannelRight);
     175#else
    101176    String resourceName = String::format("IRC_%s_C_R0195_T%03d_P%03d", subjectName.utf8().data(), azimuth, positiveElevation);
    102177
     
    118193    AudioChannel* leftEarImpulseResponse = impulseResponse->channelByType(AudioBus::ChannelLeft);
    119194    AudioChannel* rightEarImpulseResponse = impulseResponse->channelByType(AudioBus::ChannelRight);
     195#endif
    120196
    121197    // Note that depending on the fftSize returned by the panner, we may be truncating the impulse response we just loaded in.
Note: See TracChangeset for help on using the changeset viewer.