def test_delay_compensation_corrects_group_delay(self, gain): """Test automatically compensating for group delay of linear phase filter. Genearate filters to shift entire signal by a constant gain. Test that filtered signal is in phase with original signal. Args: gain: Amount to scale the input signal. """ # Create random signal to filter. output_np = gain * self.audio[0] n_frequencies = 1025 window_size = 257 magnitudes = gain * tf.ones([1, n_frequencies], dtype=tf.float32) impulse_response = core.frequency_impulse_response( magnitudes, window_size) output_tf = core.fft_convolve(self.audio, impulse_response, padding='same')[0] difference = output_np - output_tf total_difference = np.abs(difference).mean() threshold = 1e-3 self.assertLessEqual(total_difference, threshold)
def test_fft_convolve_checks_number_of_frames(self, n_frames): """Tests fft_convolve() raises error for invalid number of framess.""" # Create random signals to convolve with same batch sizes. impulse_response = tf.random.normal([1, n_frames, self.audio_size], dtype=tf.float32) with self.assertRaises(ValueError): _ = core.fft_convolve(self.audio, impulse_response)
def test_fft_convolve_checks_batch_size(self): """Tests fft_convolve() raises error for mismatched batch sizes.""" # Create random signals to convolve with different batch sizes. impulse_response = tf.concat([self.audio, self.audio], axis=0) with self.assertRaises(ValueError): _ = core.fft_convolve(self.audio, impulse_response)
def test_fft_convolve_is_accurate(self, audio_size, impulse_response_size): """Tests convolving signals using fast fourier transform (fft). Generate random signals and convolve using fft. Compare outputs to the implementation in scipy.signal. Args: audio_size: Size of the audio to convolve. impulse_response_size: Size of the impulse response to convolve. """ # Create random signals to convolve. audio = np.ones([1, audio_size]).astype(np.float32) impulse_response = np.ones([1, impulse_response_size]).astype(np.float32) output_tf = core.fft_convolve(audio, impulse_response, padding='valid', delay_compensation=0)[0] output_np = signal.fftconvolve(audio[0], impulse_response[0]) difference = output_np - output_tf total_difference = np.abs(difference).mean() threshold = 1e-3 self.assertLessEqual(total_difference, threshold)
def test_fft_convolve_disallows_invalid_padding_arguments(self, padding): """Tests fft_convolve() raises error for wrong padding name.""" with self.assertRaises(ValueError): with self.cached_session() as sess: _ = sess.run(core.fft_convolve(self.audio, self.audio, padding=padding))
def test_fft_convolve_allows_valid_padding_arguments(self, padding): """Tests fft_convolve() runs for valid padding names.""" with self.cached_session() as sess: result = sess.run(core.fft_convolve(self.audio, self.audio, padding=padding)) self.assertEqual(result.shape[0], 1)
def get_signal(self, audio, ir): """Apply impulse response. Args: audio: Dry audio, 2-D Tensor of shape [batch, n_samples]. ir: 3-D Tensor of shape [batch, ir_size, 1] or 2D Tensor of shape [batch, ir_size]. Returns: tensor of shape [batch, n_samples] """ audio, ir = tf_float32(audio), tf_float32(ir) ir = self._mask_dry_ir(ir) wet = core.fft_convolve(audio, ir, padding='same', delay_compensation=0) return (wet + audio) if self._add_dry else wet
def test_fft_convolve_allows_valid_padding_arguments(self, padding): """Tests fft_convolve() runs for valid padding names.""" result = core.fft_convolve(self.audio, self.audio, padding=padding) self.assertEqual(result.shape[0], 1)
def get_signal(self, impulse_profile: tf.Tensor, impulse_response: tf.Tensor) -> tf.Tensor: return core.fft_convolve(impulse_profile, impulse_response)