簡體   English   中英

檢測最后的過零

[英]Detect last zero-crossing

我正在使用以下 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

現在正弦波並沒有在過零處結束,所以為了避免這個問題,我設法做了一個淡入淡出的 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

問題是:

  1. 檢測陣列中的最后一個過零並使正弦波在那里結束會更好/更快嗎?
  2. 如果更好,怎么辦?

由於time_in_secondssrstarting_frequencyending_frequency都是未知的,我們不能保證它會達到任何零甚至跨越它,而不給它們任何約束。 正確執行此操作的唯一方法是使用具有已知頻率行為的 window(或淡入/淡出)。

這排除了 1。我們可以繼續 2。


我建議為此任務使用錐形余弦 window - scipy.signal.windows.tukey - 它提供從 0 到 1 和 vv 的淡入/淡出,並且是音頻任務的一個非常常見的選擇。

這方面的一個例子可以實現為 -

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

結果 window - 淡出時間為 0.1 秒 - 看起來像這樣

要將其添加到您現有的代碼中並簡化它 -

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

我們可以用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

只是一個一般性評論 - 不要將變量混合為 arguments 和不。 請全部包含在

def generate_exponential_sweep(time_in_seconds, sr, starting_frequency, ending_frequency):
...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM