【问题标题】:Convert data frame columns to one sound将数据框列转换为一种声音
【发布时间】:2017-05-04 12:24:58
【问题描述】:

我有兴趣将我的数据转换为声音。我的数据在数据框中。每列代表特定频率下声音的相对幅度。每行都是一个样本。样本以固定的采样率记录。我已经知道如何使用seewave package 发出声音,但不是在我想要的特定频率。

例子:

library(seewave)

# some dummy data, 3 columns
set.seed(7)
df <- data.frame(f1=rnorm(600,30,5), f2=rnorm(600,40,10), 3=rnorm(600,30,10))
df[df<0] <- 0

mat <- as.matrix(df)
mat <- t(mat) +0i # istft() only works with complex numbers
sr <- 1000 # sample rate in Hz
freqs <- c(500, 2000, 10000) # desired frequencies of output sounds for each column

sound <- istft(mat,f=sr,ovlp=50,wl=256,output = "Wave") # creates a sound 
listen(sound)

istft 假设:

“由短期傅里叶变换产生的复矩阵”。

我的mat 对象的格式显然不正确,所以我不确定实际输出是什么。我不知道如何将数据帧中的每一列强制转换为存储在 freqs 中的频率。

任何想法都会很棒。

【问题讨论】:

    标签: r


    【解决方案1】:

    实际上你的代码运行了,但是有一个警告说

    1: 在 xprim * win 中: 较长的对象长度不是较短对象长度的倍数

    要解决此问题,mat 的行数必须能被 2 整除并且小于 FFT 窗口长度 (wl):

    library(seewave)
    
    # some dummy data, 3 columns
    set.seed(7)
    N = 128
    df <- data.frame(f1=rnorm(N,30,5), f2=rnorm(N,40,10), f3=rnorm(N,30,10))
    df[df<0] <- 0
    
    mat <- as.matrix(df)
    #no need to transpose
    mat <- mat + 0i # istft() only works with complex numbers
    
    sr <- 1000 # sample rate in Hz
    freqs <- c(500, 2000, 10000) # desired frequencies of output sounds for each column
    
    sound <- istft(mat, f=sr, ovlp=50, wl=256, output = "Wave") # creates a sound 
    listen(sound)
    

    上面的代码不会给你那个警告。对于?istft 中提供的示例,您可以单步执行istft 代码,并让您的代码查看导致警告的原因。

    【讨论】:

    • 不错的收获。我已经找到了我的问题并会发布答案
    【解决方案2】:

    所以我设法通过使用 synth() 函数合成波来做到这一点。这通过数据帧的每一列工作,并在载波频率上创建幅度调制信号。然后,将所有列的结果相加。

    library(seewave)
    library(tuneR)
    
    nsamps <- 600 # number of samples to create
    sf <- 10 # sampling frequency of the data in Hz
    fout <- 22000 # Sample frequency of output sound (Hz)
    dout <- 10 # length of output sound file (seconds)
    
    # some dummy amplitude data, 3 columns
    df <- data.frame(f1 = sin((1:nsamps)/180*pi)+1, f2 = sin((1:nsamps)/180*pi + pi)+1, f3 = sin((1:nsamps)/90*pi)+1)
    
    mat <- as.matrix(df)
    freqs <- seq(100, 1000, length.out = ncol(mat)) # Carrier frequencies for each data column (Hz)
    
    syn <- 0 # this is the synthesised wave
    atemp <- seq(from=1, to=nrow(mat), length.out = fout*dout) # new times
    for(ii in 1:ncol(mat)){ # for each data column
      scale_data <- (mat[,ii] - min(mat[,ii]))/diff(range(mat[,ii])) # scale each column between 0 and 1, comment out for absolute amplitudes across all columns
      amp <- approx(x = 1:nrow(mat), y = scale_data, xout = atemp)$y # sample the amplitude data onto the new times
      syn <- syn + synth(f = fout, d = dout, cf = freqs[ii], output = 'wave', a = amp) # build up the total synth wave
    
    }
    
    wave <- Wave(left = syn, samp.rate=fout, bit=16) # create a wave class
    listen(wave) # listen to the sound
    

    这是创建频谱图的代码:

    t_win <- 0.5 # window length for spectrogram (s)
    n_win <- t_win/(nsamps/sf/dout)*fout # calculate the window length in samples
    spectro(wave, f=fout, flim = c(0,1.1), wl = n_win, ovlp = 75) # plot the spectrogram
    

    【讨论】:

      猜你喜欢
      • 2015-08-22
      • 2022-08-13
      • 1970-01-01
      • 2020-04-15
      • 2014-02-21
      • 2018-06-10
      • 1970-01-01
      • 2011-05-12
      • 2013-09-26
      相关资源
      最近更新 更多