def test_not_equal_when_scale_differs(self): fb1 = FrequencyBand(20, 20000) scale1 = LinearScale(fb1, 100) fb2 = FrequencyBand(20, 20000) scale2 = GeometricScale(20, 20000, 0.01, 100) self.assertNotEqual(scale1, scale2)
def test_not_equal_when_bands_differ(self): fb1 = FrequencyBand(20, 20000) scale1 = LinearScale(fb1, 100) fb2 = FrequencyBand(20, 20000) scale2 = LinearScale(fb2, 50) self.assertNotEqual(scale1, scale2)
def test_equals(self): fb1 = FrequencyBand(20, 20000) scale1 = LinearScale(fb1, 100) fb2 = FrequencyBand(20, 20000) scale2 = LinearScale(fb2, 100) self.assertEqual(scale1, scale2)
def test_can_slice_frequency_dim_with_negative_stop_hz(self): scale = LinearScale(FrequencyBand(0, 100), 10) arr = ArrayWithUnits( np.zeros((13, 10)), [IdentityDimension(), FrequencyDimension(scale)]) sliced = arr[:, :-Hertz(20)] self.assertEqual((13, 8), sliced.shape) self.assertEqual( FrequencyDimension(LinearScale(FrequencyBand(0, 80), 8)), sliced.dimensions[-1])
def test_can_access_int_index_and_frequency_band(self): tf = ArrayWithUnits( np.ones((10, 10)), dimensions=[ TimeDimension(Seconds(1), Seconds(1)), FrequencyDimension(LinearScale(FrequencyBand(0, 1000), 10)) ]) sliced = tf[0, FrequencyBand(201, 400)] self.assertEqual((2,), sliced.shape) self.assertIsInstance(sliced.dimensions[0], FrequencyDimension)
def test_ellipsis(self): scale = LinearScale(FrequencyBand(0, 10000), 100) arr = ArrayWithUnits( np.zeros((10, 3, 100)), [IdentityDimension(), TimeDimension(Seconds(1)), FrequencyDimension(scale)]) sliced = arr[..., FrequencyBand(1000, 5000)] self.assertEqual((10, 3, 41), sliced.shape) self.assertIsInstance(sliced.dimensions[0], IdentityDimension) self.assertIsInstance(sliced.dimensions[1], TimeDimension) self.assertIsInstance(sliced.dimensions[2], FrequencyDimension)
def test_can_slice_freq_dimension_with_freq_band_spanning_bins(self): frequency = Seconds(1) duration = Seconds(1) scale = LinearScale(FrequencyBand(20, 22050), 100) td = TimeDimension(frequency, duration) fd = FrequencyDimension(scale) tf = ArrayWithUnits(np.zeros((30, 100)), [td, fd]) bands = list(scale) wide_band = FrequencyBand(bands[0].start_hz, bands[9].stop_hz) sliced = tf[:, wide_band] self.assertEqual((30, 10), sliced.shape) self.assertIsInstance(sliced, ArrayWithUnits)
def test_scale_is_modified_after_slice(self): frequency = Seconds(1) duration = Seconds(1) scale = LinearScale(FrequencyBand(20, 22050), 100) td = TimeDimension(frequency, duration) fd = FrequencyDimension(scale) tf = ArrayWithUnits(np.zeros((30, 100)), [td, fd]) bands = list(scale) wide_band = FrequencyBand(bands[0].start_hz, bands[9].stop_hz) sliced = tf[:, wide_band] self.assertEqual((30, 10), sliced.shape) self.assertIsInstance(sliced, ArrayWithUnits) self.assertLess(sliced.dimensions[1].scale.stop_hz, scale.stop_hz) self.assertEqual(10, sliced.dimensions[1].scale.n_bands)
def test_can_apply_weighting_to_filter_bank(self): sr = SR11025() band = FrequencyBand(20, sr.nyquist) scale = MelScale(band, 100) bank = fir_filter_bank(scale, 256, sr, np.hanning(25)) weighted = bank * AWeighting() self.assertSequenceEqual(bank.dimensions, weighted.dimensions)
def test_can_invert_frequency_weighting(self): td = TimeDimension(Seconds(1), Seconds(1)) fd = FrequencyDimension(LinearScale(FrequencyBand(20, 22050), 100)) tf = ArrayWithUnits(np.random.random_sample((90, 100)), [td, fd]) weighted = tf * AWeighting() inverted = weighted / AWeighting() np.testing.assert_allclose(tf, inverted)
def test_can_slice_frequency_dim_with_start_and_end_hz(self): scale = LinearScale(FrequencyBand(0, 100), 10) arr = ArrayWithUnits( np.zeros((13, 10)), [IdentityDimension(), FrequencyDimension(scale)]) sliced = arr[:, Hertz(20):Hertz(80)] self.assertEqual((13, 7), sliced.shape)
def frequency_decomposition(x, sizes): sizes = sorted(sizes) if x.ndim == 1: end = x.dimensions[0].end x = ArrayWithUnits(x[None, ...], [TimeDimension(end, end), x.dimensions[0]]) original_size = x.shape[-1] time_dimension = x.dimensions[-1] samplerate = audio_sample_rate(time_dimension.samples_per_second) data = x.copy() bands = [] frequency_bands = [] start_hz = 0 for size in sizes: if size != original_size: s = resample(data, size, axis=-1) else: s = data.copy() bands.append(s) data -= resample(s, original_size, axis=-1) stop_hz = samplerate.nyquist * (size / original_size) frequency_bands.append(FrequencyBand(start_hz, stop_hz)) start_hz = stop_hz scale = ExplicitScale(frequency_bands) return FrequencyAdaptive(bands, scale=scale, time_dimension=x.dimensions[0])
def test_can_apply_a_weighting_to_time_frequency_representation(self): td = TimeDimension(Seconds(1), Seconds(1)) fd = FrequencyDimension(LinearScale(FrequencyBand(20, 22050), 100)) tf = ArrayWithUnits(np.ones((90, 100)), [td, fd]) weighting = AWeighting() result = tf * weighting self.assertGreater(result[0, -1], result[0, 0])
def test_slicing_geometric_scale_returns_explicit_scale(self): scale = GeometricScale(start_center_hz=20, stop_center_hz=5000, bandwidth_ratio=0.05, n_bands=100) sliced = scale[FrequencyBand(100, 1000)] self.assertIsInstance(sliced, ExplicitScale)
def test_can_multiply_by_frequency_weighting_linear_scale(self): frequency = Seconds(1) duration = Seconds(1) scale = LinearScale(FrequencyBand(20, 22050), 100) td = TimeDimension(frequency, duration) fd = FrequencyDimension(scale) tf = ArrayWithUnits(np.ones((30, 100)), [td, fd]) result = tf * AWeighting() self.assertIsInstance(result, ArrayWithUnits) peak_frequency_band = FrequencyBand(9000, 11000) lower_band = FrequencyBand(100, 300) peak_slice = np.abs(result[:, peak_frequency_band]).max() lower_slice = np.abs(result[:, lower_band]).max() self.assertGreater(peak_slice, lower_slice)
def test_from_example(self): td = TimeDimension(Seconds(1), Seconds(1)) fd = FrequencyDimension(LinearScale(FrequencyBand(20, 22050), 100)) tf = ArrayWithUnits(np.ones((30, 100)), [td, fd]) from_example = ArrayWithUnits.from_example(np.ones((30, 100)), tf) self.assertEqual(tf.shape, from_example.shape) self.assertItemsEqual(tf.dimensions, from_example.dimensions)
def test_can_get_weights_from_tf_representation(self): td = TimeDimension(Seconds(1), Seconds(1)) fd = FrequencyDimension(LinearScale(FrequencyBand(20, 22050), 100)) tf = ArrayWithUnits(np.ones((90, 100)), [td, fd]) weighting = AWeighting() weights = weighting.weights(tf) self.assertEqual((100, ), weights.shape)
def test_metaslice(self): scale1 = GeometricScale(20, 5000, 0.02, 3) bands = list(scale1) slices1 = [slice(0, 10), slice(10, 100), slice(100, 1000)] dim1 = ExplicitFrequencyDimension(scale1, slices1) dim2 = dim1.metaslice(FrequencyBand(15, 1000), 2) self.assertEqual(bands[:2], list(dim2.scale)[:2]) self.assertEqual(slices1[:2], dim2.slices[:2])
def test_can_construct_instance(self): frequency = Seconds(1) duration = Seconds(1) scale = LinearScale(FrequencyBand(20, 22050), 100) td = TimeDimension(frequency, duration) fd = FrequencyDimension(scale) tf = ArrayWithUnits(np.zeros((30, 100)), [td, fd]) self.assertIsInstance(tf, ArrayWithUnits)
def test_sum_along_frequency_axis(self): td = TimeDimension(Seconds(1), Seconds(1)) fd = FrequencyDimension(LinearScale(FrequencyBand(20, 22050), 100)) tf = ArrayWithUnits(np.ones((30, 100)), [td, fd]) result = tf.sum(axis=1) self.assertIsInstance(result, ArrayWithUnits) self.assertEqual(1, len(result.dimensions)) self.assertEqual((30,), result.shape) self.assertIsInstance(result.dimensions[0], TimeDimension)
def test_can_use_negative_axis_indices_max(self): td = TimeDimension(Seconds(1), Seconds(1)) fd = FrequencyDimension(LinearScale(FrequencyBand(20, 22050), 100)) tf = ArrayWithUnits(np.ones((30, 100)), [td, fd]) result = tf.max(axis=-1) self.assertIsInstance(result, ArrayWithUnits) self.assertEqual(1, len(result.dimensions)) self.assertEqual((30,), result.shape) self.assertIsInstance(result.dimensions[0], TimeDimension)
def test_can_slice_frequency_dimension_with_integer_indices(self): frequency = Seconds(1) duration = Seconds(1) scale = LinearScale(FrequencyBand(20, 22050), 100) td = TimeDimension(frequency, duration) fd = FrequencyDimension(scale) tf = ArrayWithUnits(np.zeros((30, 100)), [td, fd]) sliced = tf[:, 10: 20] self.assertEqual((30, 10), sliced.shape) self.assertIsInstance(sliced, ArrayWithUnits)
def test_can_multiply_by_array(self): frequency = Seconds(1) duration = Seconds(1) scale = LinearScale(FrequencyBand(20, 22050), 100) td = TimeDimension(frequency, duration) fd = FrequencyDimension(scale) tf = ArrayWithUnits(np.ones((30, 100)), [td, fd]) result = tf * np.ones(100) self.assertIsInstance(result, ArrayWithUnits) np.testing.assert_allclose(tf, result)
def test_can_access_time_slice_and_int_index(self): tf = ArrayWithUnits( np.ones((10, 10)), dimensions=[ TimeDimension(Seconds(1), Seconds(1)), FrequencyDimension(LinearScale(FrequencyBand(0, 1000), 10)) ]) sliced = tf[TimeSlice(start=Seconds(1), duration=Seconds(2)), 0] self.assertEqual((2,), sliced.shape) self.assertIsInstance(sliced.dimensions[0], TimeDimension)
def test_can_use_keepdims_with_sum(self): td = TimeDimension(Seconds(1), Seconds(1)) fd = FrequencyDimension(LinearScale(FrequencyBand(20, 22050), 100)) tf = ArrayWithUnits(np.ones((30, 100)), [td, fd]) result = tf.sum(axis=-1, keepdims=True) self.assertIsInstance(result, ArrayWithUnits) self.assertEqual(2, len(result.dimensions)) self.assertEqual((30, 1), result.shape) self.assertIsInstance(result.dimensions[0], TimeDimension) self.assertIsInstance(result.dimensions[1], IdentityDimension)
def test_raises_if_scale_length_does_not_match_frequency_dimension(self): frequency = Seconds(1) duration = Seconds(1) scale = LinearScale(FrequencyBand(20, 22050), 1000) td = TimeDimension(frequency, duration) fd = FrequencyDimension(scale) self.assertRaises( ValueError, lambda: ArrayWithUnits(np.ones((30, 100)), [td, fd]))
def test_can_add_axis_at_end(self): _id = IdentityDimension() td = TimeDimension(Seconds(1), Seconds(1)) fd = FrequencyDimension(LinearScale(FrequencyBand(20, 22050), 100)) tf = ArrayWithUnits(np.ones((3, 30, 100)), [_id, td, fd]) tf2 = tf[..., None] self.assertEqual(4, tf2.ndim) self.assertIsInstance(tf2.dimensions[0], IdentityDimension) self.assertIsInstance(tf2.dimensions[1], TimeDimension) self.assertIsInstance(tf2.dimensions[2], FrequencyDimension) self.assertIsInstance(tf2.dimensions[3], IdentityDimension)
def test_can_use_tuple_indices_for_first_dimension(self): tf = ArrayWithUnits( np.ones((10, 10)), dimensions=[ TimeDimension(Seconds(1), Seconds(1)), FrequencyDimension(LinearScale(FrequencyBand(0, 1000), 10)) ]) subset = tf[tuple([2, 4, 6]), ...] self.assertEqual((3, 10), subset.shape) self.assertIsInstance(subset, ArrayWithUnits) self.assertIsInstance(subset.dimensions[0], TimeDimension) self.assertIsInstance(subset.dimensions[1], FrequencyDimension)
def test_can_iterate_over_time_frequency_representation(self): tf = ArrayWithUnits( np.ones((10, 10)), dimensions=[ TimeDimension(Seconds(1), Seconds(1)), FrequencyDimension(LinearScale(FrequencyBand(0, 1000), 10)) ]) rows = [row for row in tf] self.assertEqual(10, len(rows)) for row in rows: self.assertIsInstance(row, ArrayWithUnits) self.assertIsInstance(row.dimensions[0], FrequencyDimension) self.assertEqual((10,), row.shape)
def test_can_apply_sliding_window(self): sr = SR11025() hl = sr.half_lapped() scale = GeometricScale(20, sr.nyquist, 0.175, 64) td = TimeDimension(frequency=hl.frequency, duration=hl.duration) fd = FrequencyDimension(scale) arr = ArrayWithUnits(np.zeros((99, 64)), [td, fd]) ts = TimeSlice(duration=hl.frequency * 64) fs = FrequencyBand(0, sr.nyquist) windowed = arr.sliding_window((ts, fs)) self.assertEqual((1, 64, 64), windowed.shape)