[英]Detect last zero-crossing
I'm generating an exponential sweep with the following function:我正在使用以下 function 生成指数扫描:
@jit(nopython=True)
def generate_exponential_sweep(time_in_seconds, sr):
time_in_samples = time_in_seconds * sr
exponential_sweep = np.zeros(time_in_samples, dtype=np.double)
for n in range(time_in_samples):
t = n / sr
exponential_sweep[n] = np.sin(
(2.0 * np.pi * starting_frequency * sweep_duration)
/ np.log(ending_frequency / starting_frequency)
* (np.exp((t / sweep_duration) * np.log(ending_frequency / starting_frequency)) - 1.0))
number_of_samples = 50
exponential_sweep[-number_of_samples:] = fade(exponential_sweep[-number_of_samples:], 1, 0)
return exponential_sweep
Right now the sine wave does not finish at a zero-crossing, so for avoiding the problem I managed to make a fade function that simply fades the volume to zero:现在正弦波并没有在过零处结束,所以为了避免这个问题,我设法做了一个淡入淡出的 function,它只是将音量淡化为零:
@jit(nopython=True)
def fade(data, gain_start,
gain_end):
gain = gain_start
delta = (gain_end - gain_start) / (len(data) - 1)
for i in range(len(data)):
data[i] = data[i] * gain
gain = gain + delta
return data
The question is:问题是:
Since time_in_seconds
, sr
, starting_frequency
and ending_frequency
are all unknown, we can't guarantee that it will hit any zeroes or even cross it, without any giving them any constraints.由于
time_in_seconds
、 sr
、 starting_frequency
和ending_frequency
都是未知的,我们不能保证它会达到任何零甚至跨越它,而不给它们任何约束。 The only way to properly do this is to use a window (or fade in/out), with a known frequency behaviour.正确执行此操作的唯一方法是使用具有已知频率行为的 window(或淡入/淡出)。
This rules out 1. We can continue with 2.这排除了 1。我们可以继续 2。
I would suggest a tapered cosine window for this task - scipy.signal.windows.tukey - which offers the fade-in/-out from 0 to 1 and vv, and is a very common choice for audio tasks.我建议为此任务使用锥形余弦 window - scipy.signal.windows.tukey - 它提供从 0 到 1 和 vv 的淡入/淡出,并且是音频任务的一个非常常见的选择。
An example of this can be implemented as -这方面的一个例子可以实现为 -
import numpy as np
import scipy
def fade(data: np.ndarray, fade_time: float, sr: float) -> np.ndarray:
alpha = sr * 2 * fade_time / len(data)
window = scipy.signal.windows.tukey(len(data), alpha)
return data * window
The resulting window - with a fade time of 0.1 s - would look like this结果 window - 淡出时间为 0.1 秒 - 看起来像这样
To add this to your already existing code and simplying it -要将其添加到您现有的代码中并简化它 -
import numpy as np
def generate_exponential_sweep(
time_in_seconds: float, sr: float, starting_frequency: float,
ending_frequency: float, fade_time: float) -> np.ndarray:
t = np.arange(0, time_in_seconds, 1/sr)
exponential_sweep = np.sin(2 * np.pi * (
starting_frequency * time_in_seconds * (
(ending_frequency / starting_frequency) ** (t / time_in_seconds) - 1
) / np.log(starting_frequency / ending_frequency)
)
)
exponential_sweep = fade(exponential_sweep, fade_time, sr)
return exponential_sweep
We can replace that whole block creating the sweep by scipy.signal.chirp which does exactly the same -我们可以用scipy.signal.chirp替换创建扫描的整个块,它的作用完全相同 -
import numpy as np
import scipy
def generate_exponential_sweep(
time_in_seconds: float, sr: float, starting_frequency: float,
ending_frequency: float, fade_time: float) -> np.ndarray:
t = np.arange(0, time_in_seconds, 1/sr)
exponential_sweep = scipy.signal.chirp(
t, f0=starting_frequency, f1=ending_frequency,
t1=time_in_seconds, method='logarithmic')
exponential_sweep = fade(exponential_sweep, fade_time, sr)
return exponential_sweep
And just a general comment - don't mix putting variables as arguments and not.只是一个一般性评论 - 不要将变量混合为 arguments 和不。 Please include all in
请全部包含在
def generate_exponential_sweep(time_in_seconds, sr, starting_frequency, ending_frequency):
...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.