11use std:: any:: Any ;
2+ use std:: collections:: HashMap ;
23use std:: f32:: consts:: PI ;
4+ use std:: sync:: { Mutex , OnceLock } ;
35
46use float_eq:: float_eq;
57use hrtf:: { HrirSphere , HrtfContext , HrtfProcessor , Vec3 } ;
@@ -13,6 +15,24 @@ use super::{
1315 AudioNode , ChannelConfig , ChannelConfigOptions , ChannelCountMode , ChannelInterpretation ,
1416} ;
1517
18+ /// Load the HRIR sphere for the given sample_rate
19+ ///
20+ /// The included data contains the impulse responses at 44100 Hertz, so it needs to be resampled
21+ /// for other values (which can easily take 100s of milliseconds). Therefore cache the result (per
22+ /// sample rate) in a global variable and clone it every time a new panner is created.
23+ fn load_hrir_sphere ( sample_rate : u32 ) -> HrirSphere {
24+ static INSTANCE : OnceLock < Mutex < HashMap < u32 , HrirSphere > > > = OnceLock :: new ( ) ;
25+ let cache = INSTANCE . get_or_init ( || Mutex :: new ( HashMap :: new ( ) ) ) ;
26+ let mut guard = cache. lock ( ) . unwrap ( ) ;
27+ guard
28+ . entry ( sample_rate)
29+ . or_insert_with ( || {
30+ let resource = include_bytes ! ( "../../resources/IRC_1003_C.bin" ) ;
31+ HrirSphere :: new ( & resource[ ..] , sample_rate) . unwrap ( )
32+ } )
33+ . clone ( )
34+ }
35+
1636/// Spatialization algorithm used to position the audio in 3D space
1737#[ derive( Debug , Copy , Clone , PartialEq , Eq , Default ) ]
1838pub enum PanningModelType {
@@ -549,9 +569,8 @@ impl PannerNode {
549569 let hrtf_option = match value {
550570 PanningModelType :: EqualPower => None ,
551571 PanningModelType :: HRTF => {
552- let resource = include_bytes ! ( "../../resources/IRC_1003_C.bin" ) ;
553572 let sample_rate = self . context ( ) . sample_rate ( ) as u32 ;
554- let hrir_sphere = HrirSphere :: new ( & resource [ .. ] , sample_rate) . unwrap ( ) ;
573+ let hrir_sphere = load_hrir_sphere ( sample_rate) ;
555574 Some ( HrtfState :: new ( hrir_sphere) )
556575 }
557576 } ;
0 commit comments