def test_masking_analyzer_signal_excess(self):
        signal_gen_config = sound_generation_pb2.SoundGenConfig()
        signal_gen_config.fs = 5000
        signal_gen_config.duration = 2
        signal_gen_config.pure_tone_config.center_freq = 500
        signal = Sound.sound_from_gen_config(signal_gen_config)

        noise_gen_config = sound_generation_pb2.SoundGenConfig()
        noise_gen_config.fs = 5000
        noise_gen_config.duration = 2
        noise_gen_config.flat_spectrum_noise_config.start_freq = 50
        noise_gen_config.flat_spectrum_noise_config.stop_freq = 1000
        noise_gen_config.flat_spectrum_noise_config.filter_order = 10
        noise = Sound.sound_from_gen_config(noise_gen_config)

        masking_config = masking_config_pb2.MaskingConfig()
        band_config = masking_config.auditory_band_config
        for start, stop in [(100, 200), (200, 400), (400, 800)]:
            band = band_config.auditory_bands.add()
            band.start_freq = start
            band.stop_freq = stop
        band_config.filter_order = 10
        masking_config.window_duration_ms = 250
        masking_config.window_step_ms = 250

        analyzer = masking.MaskingAnalyzer(signal, noise, masking_config)
        se = analyzer.get_signal_excess()
        self.assertTrue(
            np.all((se[FreqBand.from_limits(400, 800)] -
                    se[FreqBand.from_limits(100, 200)]) > 10))
        self.assertTrue(
            np.all((se[FreqBand.from_limits(400, 800)] -
                    se[FreqBand.from_limits(200, 400)]) > 10))
Beispiel #2
0
 def test_flat_spectrum_noise_from_gen_config(self):
     sound_gen_config = sound_generation_pb2.SoundGenConfig()
     sound_gen_config.fs = 2000
     sound_gen_config.duration = 1
     start_freq = 400
     stop_freq = 600
     sound_gen_config.flat_spectrum_noise_config.start_freq = start_freq
     sound_gen_config.flat_spectrum_noise_config.stop_freq = stop_freq
     sound_gen_config.flat_spectrum_noise_config.filter_order = 10
     test_sound = sound.Sound.sound_from_gen_config(sound_gen_config)
     self.assertEqual(len(test_sound.time_series),
                      sound_gen_config.fs * sound_gen_config.duration)
     f, t, Sxx = test_sound.compute_spectrogram(
         nperseg=test_sound.time_series.size)
     Sx = np.squeeze(Sxx)
     Sx = Sx / np.sum(Sx)
     sum_in_band = 0
     sum_out_band = 0
     for f, Sx in zip(f, Sx):
         if start_freq <= f <= stop_freq:
             sum_in_band += Sx
         else:
             sum_out_band += Sx
     self.assertGreater(sum_in_band, 0.95)
     self.assertLess(sum_out_band, 0.05)
Beispiel #3
0
 def test_chirp_from_gen_config(self):
     sound_gen_config = sound_generation_pb2.SoundGenConfig()
     sound_gen_config.fs = 2000
     sound_gen_config.duration = 1
     sound_gen_config.chirp_config.start_freq = 0
     sound_gen_config.chirp_config.stop_freq = 1000
     sound_gen_config.chirp_config.sweep_method = 0
     sound_gen_config.calibration.spl = 1
     test_sound = sound.Sound.sound_from_gen_config(sound_gen_config)
     self.assertEqual(len(test_sound.time_series),
                      sound_gen_config.fs * sound_gen_config.duration)
     f, t, Sxx = test_sound.compute_spectrogram(nperseg=64)
     # In the first half of the signal, roughly half the total energy should be
     # in frequency range less than half the center freq of the chirp. Roughly
     # zero energy should be above half the center frequency of the chirp.
     sum_in_lower_freq = 0
     sum_in_upper_freq = 0
     for f, Sx in zip(f, Sxx[:, :len(t) // 2]):
         if f <= sound_gen_config.chirp_config.stop_freq / 2:
             sum_in_lower_freq += sum(Sx)
         else:
             sum_in_upper_freq += sum(Sx)
     # Check that in the first half of the signal, all energy is at frequencies
     # less than half the center freq of the sweep.
     self.assertGreater(sum_in_lower_freq, 0.1)
     self.assertAlmostEqual(sum_in_upper_freq, 0.0, 1)
Beispiel #4
0
 def test_pure_tone_from_gen_config(self):
     sound_gen_config = sound_generation_pb2.SoundGenConfig()
     sound_gen_config.fs = 100000
     sound_gen_config.duration = 1
     sound_gen_config.pure_tone_config.center_freq = 100
     test_sound = sound.Sound.sound_from_gen_config(sound_gen_config)
     self.assertEqual(len(test_sound.time_series),
                      sound_gen_config.fs * sound_gen_config.duration)
     self.assertAlmostEqual(test_sound.time_series[0], 0)
     first_one_index = int(
         (sound_gen_config.fs /
          sound_gen_config.pure_tone_config.center_freq) * 0.25)
     self.assertAlmostEqual(test_sound.time_series[first_one_index], 1, 5)
     first_neg_one_index = int(
         (sound_gen_config.fs /
          sound_gen_config.pure_tone_config.center_freq) * 0.75)
     self.assertAlmostEqual(test_sound.time_series[first_neg_one_index], -1,
                            5)
Beispiel #5
0
    def test_get_windowed_spl_by_bands(self):
        sound_gen_config = sound_generation_pb2.SoundGenConfig()
        sound_gen_config.fs = 10000
        sound_gen_config.duration = 3
        sound_gen_config.pure_tone_config.center_freq = 1000
        test_sound = sound.Sound.sound_from_gen_config(sound_gen_config)
        band_config = masking_config_pb2.AuditoryBandConfig()
        for start, stop in [(100, 200), (900, 1100), (3000, 4000)]:
            band = band_config.auditory_bands.add()
            band.start_freq = start
            band.stop_freq = stop
        band_config.filter_order = 10
        win_duration_ms = 500
        step_ms = 500
        spls = test_sound.get_windowed_spl_by_bands(band_config,
                                                    win_duration_ms, step_ms)
        self.assertEqual(
            [sound.FreqBand(band) for band in band_config.auditory_bands],
            list(spls.keys()))
        self.assertEqual(len(list(spls.values())[0]),
                         sound_gen_config.duration * 1000 / step_ms)

        # RMS of sin with amplitude 1 ~0.707, 20*log(.707) = -3.1 dB, slightly less
        # when we apply a Tukey window before band filtering. We exclude extrema to
        # account for the window
        self.assertAlmostEqual(
            float(
                np.mean(
                    list(spls[sound.FreqBand.from_limits(
                        900, 1100)].values())[1:-1])), -3.0, 1)
        # Assert that SPL in bands not containing signal is less than -100 dB
        self.assertLess(
            np.mean(list(spls[sound.FreqBand.from_limits(100, 200)].values())),
            -100)
        self.assertLess(
            np.mean(list(spls[sound.FreqBand.from_limits(3000,
                                                         4000)].values())),
            -100)
Beispiel #6
0
 def sound_from_gen_config_path(cls, sound_gen_config_path: str) -> Sound:
     sound_gen_config = sound_generation_pb2.SoundGenConfig()
     with open(sound_gen_config_path, 'r') as f:
         text_format.Parse(f.read(), sound_generation_pb2)
     return Sound.sound_from_gen_config(sound_gen_config)