def __new__( cls, arrs, time_dimension=None, scale=None, explicit_freq_dimension=None): if not time_dimension: raise ValueError('time_dimension is required') if explicit_freq_dimension: if scale: raise ValueError( 'scale must be None when explicit_freq_dimension is supplied') if not isinstance(arrs, np.ndarray): raise ValueError( 'arrs must be a contiguous array when explicit_freq_dimension_is_supplied') return ArrayWithUnits.__new__( cls, arrs, [time_dimension, explicit_freq_dimension]) stops = list(np.cumsum([arr.shape[1] for arr in arrs])) slices = [slice(start, stop) for (start, stop) in zip([0] + stops, stops)] dimensions = [time_dimension, ExplicitFrequencyDimension(scale, slices)] array = np.concatenate(arrs, axis=1) return ArrayWithUnits.__new__(cls, array, dimensions)
def test_concatenation_with_differing_freqs_and_durations_raises(self): ts = ArrayWithUnits( np.arange(10), [TimeDimension(Seconds(1), Seconds(2))]) ts2 = ArrayWithUnits( np.arange(10, 20), [TimeDimension(Seconds(1), Seconds(1))]) self.assertRaises(ValueError, lambda: ts.concatenate(ts2))
def test_sliding_window_has_correct_dimensions(self): arr = np.random.randint(0, 255, (11025 * 2)).astype(np.int64) sr = SR11025() awu = ArrayWithUnits(arr, [TimeDimension(*sr)]) ws = TimeSlice(duration=sr.frequency * 8192) ss = TimeSlice(duration=sr.frequency * 4096) l, x = awu.sliding_window_with_leftovers(ws, ss) self.assertEqual(8192, x.shape[1])
def test_sum_along_second_axis(self): td = TimeDimension(Seconds(1), Seconds(2)) ts = ArrayWithUnits(np.ones((10, 3)), [td, IdentityDimension()]) result = ts.sum(axis=1) self.assertIsInstance(result, ArrayWithUnits) self.assertEqual((10,), result.shape) self.assertEqual(1, len(result.dimensions)) self.assertIsInstance(result.dimensions[0], TimeDimension)
def _first_chunk(self, data): if self._padwith: padding = np.zeros( (self._padwith,) + data.shape[1:], dtype=data.dtype) padding_ts = ArrayWithUnits(padding, data.dimensions) return padding_ts.concatenate(data) else: return data
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_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_sum_2d_timeseries(self): arr = np.zeros((10, 3)) freq = Seconds(1) ts = ArrayWithUnits(arr, [TimeDimension(freq), IdentityDimension()]) ts2 = ts.sum(axis=1) self.assertIsInstance(ts2, ArrayWithUnits) self.assertEqual(1, len(ts2.dimensions)) self.assertEqual(freq, ts2.dimensions[0].frequency) self.assertEqual(freq, ts2.dimensions[0].duration)
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_concatenation_with_matching_freqs_and_duration_results_in_crts( self): ts = ArrayWithUnits( np.ones((10, 3)), [TimeDimension(Seconds(1), Seconds(2)), IdentityDimension()]) ts2 = ArrayWithUnits( np.ones((13, 3)), [TimeDimension(Seconds(1), Seconds(2)), IdentityDimension()]) result = ts.concatenate(ts2) self.assertIsInstance(result, ArrayWithUnits) self.assertEqual((23, 3), result.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)
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.assertSequenceEqual(tf.dimensions, from_example.dimensions)
def setUp(self): self.samplerate = SR44100() rs = resampled(resample_to=self.samplerate) wscheme = HalfLapped() @simple_in_memory_settings class Document(rs): windowed = ArrayWithUnitsFeature( SlidingWindow, wscheme=wscheme, wfunc=OggVorbisWindowingFunc(), needs=rs.resampled, store=False) fft = ArrayWithUnitsFeature( FFT, needs=windowed, store=False) centroid = ArrayWithUnitsFeature( SpectralCentroid, needs=fft, store=True) ss = SineSynthesizer(self.samplerate) chunks = \ [ss.synthesize(Seconds(1), [440 * i]) for i in range(1, 6)] self.audio = \ AudioSamples(ArrayWithUnits.concat(chunks), self.samplerate) _id = Document.process(meta=self.audio.encode()) self.doc = Document(_id)
def test_concat_with_differing_durations(self): td1 = TimeDimension(Seconds(1), Seconds(2)) ts1 = ArrayWithUnits(np.ones((10, 3)), [td1, IdentityDimension()]) td2 = TimeDimension(Seconds(1), Seconds(3)) ts2 = ArrayWithUnits(np.ones((13, 3)), [td2, IdentityDimension()]) self.assertRaises( ValueError, lambda: ArrayWithUnits.concat([ts1, ts2]))
def test_concat_along_first_axis(self): td1 = TimeDimension(Seconds(1), Seconds(2)) ts1 = ArrayWithUnits(np.ones((10, 3)), [td1, IdentityDimension()]) td2 = TimeDimension(Seconds(1), Seconds(2)) ts2 = ArrayWithUnits(np.ones((13, 3)), [td2, IdentityDimension()]) result = ArrayWithUnits.concat([ts1, ts2]) self.assertEqual((23, 3), result.shape)
def test_concat_with_differing_freqs(self): ts = ArrayWithUnits( np.ones((10, 3)), [TimeDimension(Seconds(2), Seconds(2)), IdentityDimension()]) ts2 = ArrayWithUnits( np.ones((13, 3)), [TimeDimension(Seconds(1), Seconds(2)), IdentityDimension()]) self.assertRaises( ValueError, lambda: ArrayWithUnits.concat([ts, ts2]))
def test_concat_along_second_axis(self): td1 = TimeDimension(Seconds(1), Seconds(2)) ts1 = ArrayWithUnits(np.ones((10, 3)), [td1, IdentityDimension()]) td2 = TimeDimension(Seconds(1), Seconds(2)) ts2 = ArrayWithUnits(np.ones((10, 5)), [td2, IdentityDimension()]) result = ArrayWithUnits.concat([ts1, ts2], axis=1) self.assertEqual((10, 8), result.shape) self.assertIsInstance(result.dimensions[0], TimeDimension) self.assertIsInstance(result.dimensions[1], IdentityDimension)
def test_can_iterate_after_packbits(self): tf = ArrayWithUnits( np.random.binomial(1, 0.5, (10, 256)).astype(np.uint8), dimensions=[ TimeDimension(Seconds(1), Seconds(1)), IdentityDimension() ]) tf = tf.packbits(axis=1) self.assertIsInstance(tf, ArrayWithUnits) self.assertEqual((10, 32), tf.shape) self.assertIsInstance(tf.dimensions[0], TimeDimension) self.assertIsInstance(tf.dimensions[1], IdentityDimension) rows = [row for row in tf] self.assertEqual(10, len(rows)) for row in rows: self.assertIsInstance(row, ArrayWithUnits) self.assertIsInstance(row.dimensions[0], IdentityDimension) self.assertEqual((32,), row.shape)
def __new__(cls, array): try: dim = array.dimensions[0] except AttributeError: raise ValueError('array must be of type ArrayWithUnits') if not isinstance(dim, TimeDimension): raise ValueError('array first dimension must be a TimeDimension') return ArrayWithUnits.__new__(cls, array, array.dimensions)
def __new__(cls, array, samplerate): if array.ndim == 1: dimensions = [TimeDimension(*samplerate)] elif array.ndim == 2: dimensions = [TimeDimension(*samplerate), IdentityDimension()] else: raise ValueError( 'array must be one (mono) or two (multi-channel) dimensions') if not isinstance(samplerate, AudioSampleRate): raise TypeError('samplerate should be an AudioSampleRate instance') return ArrayWithUnits.__new__(cls, array, dimensions)
def synthesize(self, freq_adaptive_coeffs): fac = freq_adaptive_coeffs linear_scale = LinearScale.from_sample_rate( self.samplerate, self._n_linear_scale_bands(fac), always_even=self.scale_slices_always_even) frequency_dimension = FrequencyDimension(linear_scale) coeffs = ArrayWithUnits( np.zeros((len(fac), linear_scale.n_bands), dtype=self.coeffs_dtype), dimensions=[fac.dimensions[0], frequency_dimension]) for band in self.scale: coeffs[:, band] += self.band_transform(fac[:, band], norm='ortho') return self.short_time_synth.synthesize(coeffs)
def test_can_dequeue_when_reservoir_is_partially_full(self): sampler = ReservoirSampler(nsamples=10) frequency_dimension = FrequencyDimension( LinearScale(FrequencyBand(100, 1000), 100)) samples = ArrayWithUnits(np.ones((4, 10, 100)), [ TimeDimension(frequency=Seconds(10)), TimeDimension(frequency=Seconds(1)), frequency_dimension ]) sampler._enqueue(samples, pusher=None) reservoir = sampler._dequeue() self.assertEqual((4, 10, 100), reservoir.shape) self.assertIsInstance(reservoir, ArrayWithUnits) self.assertEqual(reservoir.dimensions[0], IdentityDimension()) self.assertEqual(reservoir.dimensions[1], samples.dimensions[1]) self.assertEqual(reservoir.dimensions[2], samples.dimensions[2])
def test_iter_slices_yields_evenly_spaced_time_slices(self): raw = np.random.random_sample((10, 3)) arr = ArrayWithUnits(raw, dimensions=[ TimeDimension(frequency=Milliseconds(500), duration=Seconds(1)), IdentityDimension() ]) crts = ConstantRateTimeSeries(arr) slices = list(crts.iter_slices()) self.assertEqual(10, len(slices)) ts1, d1 = slices[0] self.assertEqual(TimeSlice(start=Seconds(0), duration=Seconds(1)), ts1) np.testing.assert_allclose(raw[0], d1) ts2, d2 = slices[1] self.assertEqual( TimeSlice(start=Milliseconds(500), duration=Seconds(1)), ts2) np.testing.assert_allclose(raw[1], d2)
def test_can_apply_sliding_window_to_constant_rate_time_series(self): arr = ArrayWithUnits(np.zeros(100), [TimeDimension(Seconds(1))]) sw = SampleRate(Seconds(2), Seconds(2)) @simple_in_memory_settings class Document(BaseModel): windowed = ArrayWithUnitsFeature(SlidingWindow, wscheme=sw, store=True) _id = Document.process(windowed=arr) result = Document(_id).windowed self.assertIsInstance(result, ArrayWithUnits) self.assertEqual((50, 2), result.shape) self.assertEqual(2, len(result.dimensions)) self.assertIsInstance(result.dimensions[0], TimeDimension) self.assertEqual(Seconds(2), result.dimensions[0].frequency) self.assertIsInstance(result.dimensions[1], TimeDimension) self.assertEqual(Seconds(1), result.dimensions[1].frequency)
def fir_filter_bank(scale, taps, samplerate, window): basis = np.zeros((len(scale), taps)) basis = ArrayWithUnits( basis, [FrequencyDimension(scale), TimeDimension(*samplerate)]) nyq = samplerate.nyquist if window.ndim == 1: window = repeat(window, len(scale)) for i, band, win in zip(range(len(scale)), scale, window): start_hz = max(0, band.start_hz) stop_hz = min(nyq, band.stop_hz) freqs = np.linspace(start_hz / nyq, stop_hz / nyq, len(win)) freqs = [0] + list(freqs) + [1] gains = [0] + list(win) + [0] basis[i] = firwin2(taps, freqs, gains) return basis
def x(d, network=None, apply_network=None): from zounds.core import ArrayWithUnits, IdentityDimension from zounds.learn import apply_network as apply import numpy as np if apply_network == 'generator': n = network.generator else: n = network.discriminator result = apply(n, d.astype(np.float32), chunksize=128) try: return ArrayWithUnits( result, d.dimensions[:-1] + (IdentityDimension(), )) except AttributeError: return result except ValueError: # the number of dimensions has likely changed return result
def test_forward_transform_returns_array_with_units_where_possible(self): # train the model on random data training = np.random.random_sample((100, 30)) Model = self.get_model() _id = Model.process(unitnorm=training) model = Model(_id) # create a time-frequency representation scale = LinearScale(FrequencyBand(20, 20000), 30) data = ArrayWithUnits(np.random.random_sample( (10, 30)), [TimeDimension(Seconds(1)), FrequencyDimension(scale)]) # do a forward pass transformed = model.pipeline.transform(data).data self.assertIsInstance(transformed, ArrayWithUnits) self.assertEqual(2, len(transformed.dimensions)) self.assertIsInstance(transformed.dimensions[0], TimeDimension) self.assertIsInstance(transformed.dimensions[1], IdentityDimension)
def transform(self, samples, pooling_kernel_size, pooling_stride): # convert the raw audio samples to a PyTorch tensor tensor_samples = torch.from_numpy(samples).float() \ .to(self.filter_bank.device) # compute the transform spectral = self.convolve(tensor_samples) log_magnitude = self.log_magnitude(spectral) pooled = self.temporal_pooling(log_magnitude, pooling_kernel_size, pooling_stride) # convert back to an ArrayWithUnits instance samplerate = samples.samplerate time_frequency = pooled.data.cpu().numpy().squeeze().T time_frequency = ArrayWithUnits(time_frequency, [ TimeDimension(frequency=samplerate.frequency * pooling_stride, duration=samplerate.frequency * pooling_kernel_size), FrequencyDimension(self.scale) ]) return time_frequency
def rainbowgram(time_frequency_repr, colormap=cm.rainbow): # magnitudes on a log scale, and shifted and # scaled to the unit interval magnitudes = np.abs(time_frequency_repr.real) magnitudes = log_modulus(magnitudes * 1000) magnitudes = unit_scale(magnitudes) angles = np.angle(time_frequency_repr) angles = np.unwrap(angles, axis=0) angles = np.gradient(angles)[0] angles = unit_scale(angles) colors = colormap(angles) colors *= magnitudes[..., None] # exclude the alpha channel, if there is one colors = colors[..., :3] arr = ArrayWithUnits( colors, time_frequency_repr.dimensions + (IdentityDimension(), )) return arr
def phase_shift(coeffs, samplerate, time_shift, axis=-1, frequency_band=None): frequency_dim = coeffs.dimensions[axis] if not isinstance(frequency_dim, FrequencyDimension): raise ValueError( 'dimension {axis} of coeffs must be a FrequencyDimension instance, ' 'but was {cls}'.format(axis=axis, cls=frequency_dim.__class__)) n_coeffs = coeffs.shape[axis] shift_samples = int(time_shift / samplerate.frequency) shift = (np.arange(0, n_coeffs) * 2j * np.pi) / n_coeffs shift = np.exp(-shift * shift_samples) shift = ArrayWithUnits(shift, [frequency_dim]) frequency_band = frequency_band or slice(None) new_coeffs = coeffs.copy() if coeffs.ndim == 1: new_coeffs[frequency_band] *= shift[frequency_band] return new_coeffs slices = [slice(None) for _ in range(coeffs.ndim)] slices[axis] = frequency_band new_coeffs[tuple(slices)] *= shift[frequency_band] return new_coeffs
def test_samplerate_one_per_second(self): arr = np.arange(10) freq = Seconds(1) ts = ArrayWithUnits(arr, [TimeDimension(freq)]) self.assertEqual(1, ts.dimensions[0].samples_per_second)
def _process(self, data): x = self._preprocess(data) x = self.scale.apply(x, self.window) yield ArrayWithUnits(x, data.dimensions[:-1] + (self._new_dim(), ))
def test_samplerate_audio(self): arr = np.arange(10) freq = Picoseconds(int(1e12)) / 44100. ts = ArrayWithUnits(arr, [TimeDimension(freq)]) self.assertEqual(44100, int(ts.dimensions[0].samples_per_second))
def test_samplerate_three_per_second(self): arr = np.arange(10) freq = Milliseconds(333) ts = ArrayWithUnits(arr, [TimeDimension(freq)]) self.assertEqual(3, int(ts.dimensions[0].samples_per_second))
def _process(self, data): for i in xrange(0, self.total_frames, self.increments_of): size = min(self.increments_of, self.total_frames - i) td = TimeDimension(frequency=Milliseconds(500)) yield ArrayWithUnits(np.zeros((size, self.features)), [td, IdentityDimension()])
def test_concatenation_with_differing_freqs_and_durations_raises(self): ts = ArrayWithUnits(np.arange(10), [TimeDimension(Seconds(1), Seconds(2))]) ts2 = ArrayWithUnits(np.arange(10, 20), [TimeDimension(Seconds(1), Seconds(1))]) self.assertRaises(ValueError, lambda: ts.concatenate(ts2))
def test_can_maintain_array_dimensions_with_supervised_learning(self): trainer = SupervisedTrainer( model=SupervisedNetwork(), loss=nn.BCELoss(), optimizer=lambda model: SGD(model.parameters(), lr=0.2), epochs=1, batch_size=64, data_preprocessor=lambda x: x.astype(np.float32), label_preprocessor=lambda x: x.astype(np.float32)) @simple_in_memory_settings class Pipeline(ff.BaseModel): inp = ff.PickleFeature(ff.IteratorNode, store=False) samples = ff.PickleFeature(ShuffledSamples, nsamples=500, multiplexed=True, dtype=np.float32, needs=inp, store=False) unitnorm = ff.PickleFeature(UnitNorm, needs=samples.aspect('data'), store=False) hard_labels = ff.PickleFeature(Binarize, needs=samples.aspect('labels'), store=False) network = ff.PickleFeature(PyTorchNetwork, trainer=trainer, needs=dict(data=unitnorm, labels=hard_labels), store=False) pipeline = ff.PickleFeature(PreprocessingPipeline, needs=(unitnorm, network), store=True) # Produce some random points on the unit circle samples = np.random.random_sample((1000, 2)) samples /= np.linalg.norm(samples, axis=1, keepdims=True) # a line extending from the origin to (1, 1) origin = np.array([0, 0]) unit = np.array([1, 1]) # which side of the plane is each sample on? labels = np.sign(np.cross(unit - origin, origin - samples)) labels[labels < 0] = 0 # scale each sample randomly, forcing the pipeline to normalize data factors = np.random.randint(1, 1000, (len(samples), 1)) scaled_samples = samples * factors scaled_samples = scaled_samples # fuzz the labels, forcing the pipeline to binarize these (i.e., force # them to be 0 or 1) fuzzed_labels = labels + np.random.normal(0, 0.1, labels.shape) fuzzed_labels = fuzzed_labels[..., None] def gen(chunksize, s, l): for i in xrange(0, len(s), chunksize): sl = slice(i, i + chunksize) yield dict(data=s[sl], labels=l[sl]) _id = Pipeline.process(inp=gen(100, scaled_samples, fuzzed_labels)) pipe = Pipeline(_id) # produce some new samples new_samples = np.random.random_sample((1000, 2)) new_samples /= np.linalg.norm(samples, axis=1, keepdims=True) # scale each example randomly, so the pipeline must give it unit norm # to arrive at the correct answer new_factors = np.random.randint(1, 1000, (len(samples), 1)) new_scaled_samples = new_factors * new_samples arr = ArrayWithUnits(new_scaled_samples, dimensions=[ TimeDimension(Seconds(1)), FrequencyDimension( LinearScale(FrequencyBand(100, 1000), 2)) ]) result = pipe.pipeline.transform(arr.astype(np.float32)) self.assertIsInstance(result.data, ArrayWithUnits) self.assertIsInstance(result.data.dimensions[0], TimeDimension)
def _process(self, data): data = np.abs(data) mean = data.mean(axis=1) mean[mean == 0] = -1e5 flatness = gmean(data, axis=1) / mean yield ArrayWithUnits(flatness, data.dimensions[:1])
def _process(self, data): yield ArrayWithUnits.concat(list(data.values()), axis=1)
def apply_scale(short_time_fft, scale, window=None): magnitudes = np.abs(short_time_fft.real) spectrogram = scale.apply(magnitudes, window) dimensions = short_time_fft.dimensions[:-1] + (FrequencyDimension(scale), ) return ArrayWithUnits(spectrogram, dimensions)
def test_duration_in_seconds_two_seconds(self): arr = np.arange(10) freq = Seconds(2) ts = ArrayWithUnits(arr, [TimeDimension(freq)]) self.assertEqual(2, ts.dimensions[0].duration_in_seconds)
def test_can_maintain_array_dimensions_with_supervised_learning(self): trainer = SupervisedTrainer( model=SupervisedNetwork(), loss=nn.BCELoss(), optimizer=lambda model: SGD(model.parameters(), lr=0.2), epochs=1, batch_size=64, data_preprocessor=lambda x: x.astype(np.float32), label_preprocessor=lambda x: x.astype(np.float32)) @simple_in_memory_settings class Pipeline(ff.BaseModel): inp = ff.PickleFeature( ff.IteratorNode, store=False) samples = ff.PickleFeature( ShuffledSamples, nsamples=500, multiplexed=True, dtype=np.float32, needs=inp, store=False) unitnorm = ff.PickleFeature( UnitNorm, needs=samples.aspect('data'), store=False) hard_labels = ff.PickleFeature( Binarize, needs=samples.aspect('labels'), store=False) network = ff.PickleFeature( PyTorchNetwork, trainer=trainer, needs=dict(data=unitnorm, labels=hard_labels), store=False) pipeline = ff.PickleFeature( PreprocessingPipeline, needs=(unitnorm, network), store=True) # Produce some random points on the unit circle samples = np.random.random_sample((1000, 2)) samples /= np.linalg.norm(samples, axis=1, keepdims=True) # a line extending from the origin to (1, 1) origin = np.array([0, 0]) unit = np.array([1, 1]) # which side of the plane is each sample on? labels = np.sign(np.cross(unit - origin, origin - samples)) labels[labels < 0] = 0 # scale each sample randomly, forcing the pipeline to normalize data factors = np.random.randint(1, 1000, (len(samples), 1)) scaled_samples = samples * factors scaled_samples = scaled_samples # fuzz the labels, forcing the pipeline to binarize these (i.e., force # them to be 0 or 1) fuzzed_labels = labels + np.random.normal(0, 0.1, labels.shape) fuzzed_labels = fuzzed_labels[..., None] def gen(chunksize, s, l): for i in range(0, len(s), chunksize): sl = slice(i, i + chunksize) yield dict(data=s[sl], labels=l[sl]) _id = Pipeline.process(inp=gen(100, scaled_samples, fuzzed_labels)) pipe = Pipeline(_id) # produce some new samples new_samples = np.random.random_sample((1000, 2)) new_samples /= np.linalg.norm(samples, axis=1, keepdims=True) # scale each example randomly, so the pipeline must give it unit norm # to arrive at the correct answer new_factors = np.random.randint(1, 1000, (len(samples), 1)) new_scaled_samples = new_factors * new_samples arr = ArrayWithUnits( new_scaled_samples, dimensions=[ TimeDimension(Seconds(1)), FrequencyDimension(LinearScale(FrequencyBand(100, 1000), 2)) ]) result = pipe.pipeline.transform(arr.astype(np.float32)) self.assertIsInstance(result.data, ArrayWithUnits) self.assertIsInstance(result.data.dimensions[0], TimeDimension)
def _process(self, data): if self._unit_norm: data = safe_unit_norm(data) diff = np.diff(data, axis=0) yield ArrayWithUnits(np.linalg.norm(diff, axis=-1), data.dimensions)
def test_span_duration_less_than_frequency(self): arr = np.arange(10) freq = Seconds(1) duration = Milliseconds(500) ts = ArrayWithUnits(arr, [TimeDimension(freq, duration)]) self.assertEqual(TimeSlice(Milliseconds(9500)), ts.dimensions[0].span)
def test_span_freq_and_duration_equal(self): arr = np.arange(10) freq = Seconds(1) ts = ArrayWithUnits(arr, [TimeDimension(freq)]) self.assertEqual(TimeSlice(Seconds(10)), ts.dimensions[0].span)
def time_stretch(x, factor, frame_sample_rate=None): if frame_sample_rate is None: sr = HalfLapped() sr = SampleRate(frequency=sr.frequency / 2, duration=sr.duration) else: sr = frame_sample_rate hop_length, window_length = sr.discrete_samples(x) win = WindowingFunc(windowing_func=hann) # to simplify, let's always compute the stft in "batch" mode if x.ndim == 1: x = x.reshape((1, ) + x.shape) print('In time_stretch', x.shape, x.dimensions) D = stft(x, sr, win) n_fft_coeffs = D.shape[-1] n_frames = D.shape[1] n_batches = D.shape[0] time_steps = np.arange(0, n_frames, factor, dtype=np.float) weights = np.mod(time_steps, 1.0) exp_phase_advance = np.linspace(0, np.pi * hop_length, n_fft_coeffs) # pad in the time dimension, so no edge/end frames are left out # coeffs = np.pad(D, [(0, 0), (0, 2), (0, 0)], mode='constant') shape = list(D.shape) shape[1] += 2 coeffs = np.zeros(shape, dtype=D.dtype) coeffs[:, :-2, :] = D coeffs_mags = np.abs(coeffs) coeffs_phases = np.angle(coeffs) # we need a phase accumulator for every item in the batch phase_accum = coeffs_phases[:, :1, :] sliding_indices = np.vstack([time_steps, time_steps + 1]).T.astype(np.int32) windowed_mags = coeffs_mags[:, sliding_indices, :] windowed_phases = coeffs_phases[:, sliding_indices, :] first_mags = windowed_mags[:, :, 0, :] second_mags = windowed_mags[:, :, 1, :] first_phases = windowed_phases[:, :, 0, :] second_phases = windowed_phases[:, :, 1, :] # compute all the phase stuff two_pi = 2.0 * np.pi dphase = (second_phases - first_phases - exp_phase_advance) dphase -= two_pi * np.round(dphase / two_pi) dphase += exp_phase_advance all_phases = np.concatenate([phase_accum, dphase], axis=1) dphase = np.cumsum(all_phases, axis=1, out=all_phases) dphase = dphase[:, :-1, :] # linear interpolation of FFT coefficient magnitudes weights = weights[None, :, None] mags = ((1.0 - weights) * first_mags) + (weights * second_mags) # combine magnitudes and phases new_coeffs = mags * np.exp(1.j * dphase) # synthesize the new frames new_frames = np.fft.irfft(new_coeffs, axis=-1, norm='ortho') # new_frames = new_frames * win._wdata(new_frames.shape[-1]) new_frames = np.multiply(new_frames, win._wdata(new_frames.shape[-1]), out=new_frames) # overlap add the new audio samples new_n_samples = int(x.shape[-1] / factor) output = np.zeros((n_batches, new_n_samples), dtype=x.dtype) for i in range(new_frames.shape[1]): start = i * hop_length stop = start + new_frames.shape[-1] l = output[:, start:stop].shape[1] output[:, start:stop] += new_frames[:, i, :l] return ArrayWithUnits(output, [IdentityDimension(), x.dimensions[-1]])
def test_get_index_error_when_using_out_of_range_int_index(self): arr = np.arange(10) freq = Seconds(1) ts = ArrayWithUnits(arr, [TimeDimension(freq)]) self.assertRaises(IndexError, lambda: ts[100])
def synthesize(self, frames): audio = self._transform(frames) ts = ArrayWithUnits(audio, [frames.dimensions[0], IdentityDimension()]) return self._overlap_add(ts)
def test_cannot_multiply_when_array_does_not_have_expected_dimensions(self): td = TimeDimension(Seconds(1), Seconds(1)) tf = ArrayWithUnits(np.ones((90, 100)), [td, IdentityDimension()]) weighting = AWeighting() self.assertRaises(ValueError, lambda: tf * weighting)
def pack(x): arr = np.zeros((len(x), 16), dtype=np.uint64) return ArrayWithUnits(arr, [x.dimensions[0], IdentityDimension()])
def test_duration_in_seconds_half_second(self): arr = np.arange(10) freq = Milliseconds(500) ts = ArrayWithUnits(arr, [TimeDimension(freq)]) self.assertEqual(0.5, ts.dimensions[0].duration_in_seconds)