Beispiel #1
0
 def test_calculate_shift_scaling_skewnorm(self):
   desired_mean = 50
   desired_variance = 5
   shift, scale = distributions.calculate_shift_scaling_skewnorm(
       desired_mean=desired_mean, desired_variance=desired_variance, alpha=4)
   actual_mean, actual_variance = scipy.stats.skewnorm.stats(
       4, loc=shift, scale=scale)
   self.assertEqual(desired_mean, actual_mean)
   self.assertEqual(desired_variance, actual_variance)
Beispiel #2
0
 def test_calculate_shift_scaling_skewnorm_neg_shift(self):
   desired_variance = 0.40082844953639396
   desired_mean = -4.225938277355348
   expected_scale = 1
   expected_shift = -5
   actual_shift, actual_scale = distributions.calculate_shift_scaling_skewnorm(
       desired_mean=desired_mean, desired_variance=desired_variance, alpha=4)
   self.assertAlmostEqual(expected_shift, actual_shift, places=7)
   self.assertAlmostEqual(expected_scale, actual_scale, places=7)
Beispiel #3
0
 def test_calculate_shift_scaling_skewnorm_upscale(self):
   desired_variance = 1.708168819476707
   desired_mean = 2.486120486787904
   expected_scale = 2
   expected_shift = 4
   actual_shift, actual_scale = distributions.calculate_shift_scaling_skewnorm(
       desired_mean=desired_mean, desired_variance=desired_variance, alpha=-3)
   self.assertAlmostEqual(expected_shift, actual_shift, places=7)
   self.assertAlmostEqual(expected_scale, actual_scale, places=7)
Beispiel #4
0
 def test_calculate_shift_scaling_skewnorm_standardnormal(self):
   desired_variance = 0.40082844953639396
   desired_mean = 0.7740617226446519
   expected_scale = 1
   expected_shift = 0
   actual_shift, actual_scale = distributions.calculate_shift_scaling_skewnorm(
       desired_mean=desired_mean, desired_variance=desired_variance, alpha=4)
   self.assertAlmostEqual(expected_shift, actual_shift, places=7)
   self.assertAlmostEqual(expected_scale, actual_scale, places=7)
Beispiel #5
0
 def test_sample_skewed_distribution(self):
   desired_mean = 50
   desired_variance = 5
   shift, scale = distributions.calculate_shift_scaling_skewnorm(
       desired_mean=desired_mean, desired_variance=desired_variance, alpha=4)
   sampled_values = distributions.sample_skewed_distribution(shift=shift,
                                                             scale=scale,
                                                             alpha=4,
                                                             num_samples=1000)
   actual_mean = np.mean(sampled_values)
   actual_variance = np.var(sampled_values)
   self.assertAlmostEqual(actual_mean, desired_mean, places=0)
   self.assertAlmostEqual(actual_variance, desired_variance, places=0)
Beispiel #6
0
def generate_data(
        num_examples_per_cb: int,
        min_tones: int,
        max_tones: int,
        clip_db: int,
        desired_skewness: int,
        desired_mean: int,
        desired_variance: int,
        min_frequency: int,
        max_frequency: int,
        critical_bands: List[int],
        min_phons=0,
        max_phons=80,
        max_iterations=1000000) -> Dict[int, List[Dict[str, List[int]]]]:
    """Generates all listening data.

  Generates examples until each critical band has exactly
  `num_examples_per_cb` number of examples.
  TODO(lauraruis): check if n_per_cb cannot be generated (e.g.
  due to too large beatrange)

  Args:
    num_examples_per_cb: how many frequencies to sample per CB
    min_tones: minimum number of frequencies per example
    max_tones: maximum number of frequencies per example
    clip_db: maximum spl
    desired_skewness: skewness of skewed normal distr. for phons
    desired_mean: mean of skewed normal distr. for phons
    desired_variance: variance of skewed normal distr. for phons
    min_frequency: below this frequency no tones will be generated
    max_frequency: above this frequency no tones will be generated
    critical_bands: list of critical bands
    min_phons: minimum level of phons for examples
    max_phons: maximum level of phons for examples
    max_iterations: how long to try combining examples

  Returns:
    Dict with data examples.
  """
    # Initialize the structures for keeping the data.
    data = {i: [] for i in range(min_tones, max_tones + 1)}
    num_examples = 0

    # Calculate the needed shift and scaling for the SN distribution over phons.
    sn_shift, sn_scale = distributions.calculate_shift_scaling_skewnorm(
        desired_variance=desired_variance,
        desired_mean=desired_mean,
        alpha=desired_skewness)

    # Sample n examples per critical band.
    examples_per_cb = sample_n_per_cb(num_examples_per_cb, critical_bands)

    # Generate examples by combining a subset of tones until they run out.
    while len(examples_per_cb) >= min_tones:
        # Sample a number of tones for the example.
        num_tones = min(len(examples_per_cb),
                        random.randint(min_tones, max_tones))

        # If less than max_tones examples left, check how far apart they are.
        if len(examples_per_cb) <= max_tones:
            if not check_frequencies(
                    np.array([ex.frequency for ex in examples_per_cb]),
                    min_frequency, max_frequency):
                break

        # Sample frequencies from the pre-generated tones until they satisfy the
        # constraint of being beat_range apart.
        frequencies = np.array([100] * num_tones)
        iteration = 0
        while not check_frequencies(
                frequencies, min_frequency,
                max_frequency) and iteration < max_iterations:
            sampled_idxs = random.sample(range(len(examples_per_cb)),
                                         k=num_tones)
            for i, sampled_idx in enumerate(sampled_idxs):
                frequencies[i] = examples_per_cb[sampled_idx].frequency
            iteration += 1
        # If the correct frequencies weren't found, stop generation.
        if iteration >= max_iterations:
            print("WARNING: didn't find correct frequencies: ", frequencies)
            break

        # Delete the used tones from the pregenerated list.
        for sampled_idx in sorted(sampled_idxs, reverse=True):
            del examples_per_cb[sampled_idx]

        # Sample phons for each tone on a skewed normal distribution.
        phons = np.array([100] * num_tones)
        while not check_phons(phons, min_phons, max_phons):
            phons = distributions.sample_skewed_distribution(
                sn_shift,
                sn_scale,
                num_samples=num_tones,
                alpha=desired_skewness)
            phons = np.round(phons)
        num_examples += 1

        # Convert phons to sound pressure level in decibel with the ISO 226.
        sp_levels = [
            np.round(
                loudness.loudness_to_spl(loudness_phon=loudness_phons,
                                         frequency=frequency))
            for loudness_phons, frequency in zip(phons, frequencies)
        ]
        sp_levels = np.clip(np.array(sp_levels), a_min=0, a_max=clip_db)

        data[num_tones].append({
            "frequencies": list(frequencies),
            "phons": list(phons),
            "levels": list(sp_levels)
        })
    return data