How to split audio files wherever there is silence

602 views Asked by At

The code as follows can split wav.file but there is a limitation which you need to set up the duration to cut audio files. May I ask if there are any solutions in R that are able to split audio files wherever there is silence?

 library(seewave)
 #your audio file (using example file from seewave package)
 data(tico)
 audio <- tico
 #the frequency of your audio file
 freq <- 22050
  # the length and duration of your audio file
 totlen <- length(audio)
 totsec <- totlen/freq

  # the duration that you want to chop the file into
  seglen <- 0.5

  # defining the break points
  breaks <- unique(c(seq(0, totsec, seglen), totsec))
  index <- 1:(length(breaks)-1)
  # a list of all the segments
  lapply(index, function(i) audio[(breaks[i]*freq):(breaks[i+1]*freq)])
  # the above final line is the only difference between this code and the 
   # code provided by @Jean V. Adams
1

There are 1 answers

0
Andrew Chisholm On

The seewave package contains the function timer which detects where silence and signal are. Some care is needed to get the threshold, smoothing and minimum duration correct but here's an example.

    library(seewave)
    # make some example data
    sine <- synth(cf=1000, f = 22050, d = 2, output = 'Wave')
    sinewithsilence <- addsilw(wave = sine, at = 'middle', output = 'Wave', d = 0.5)
    testsignal1 <- pastew(sinewithsilence, sinewithsilence, output = 'Wave')
    testsignal2 <- addsilw(wave = testsignal1, at = 'end', output = 'Wave', d = 0.5)

    # choose one wav to split - uncomment as necessary
    #signal <- tico
    #signal <- testsignal1
    signal <- testsignal2
    totsec <- length(signal@left)/[email protected]
    periods <- timer(signal, plot = T, threshold = 1, msmooth = c(100,0), dmin=0.1)

    starts <- periods$s.start
    ends <- periods$s.end
    if (length(starts) > length(ends)) {
        ends <- c(ends, totsec)
    }
    periods.df <- data.frame(starts, ends)

    splits = lapply(1:nrow(periods.df), function(i) cutw(signal, from = periods.df$starts[i], to = periods.df$ends[i], output = 'Wave'))

> str(splits)
List of 3
 $ :Formal class 'Wave' [package "tuneR"] with 6 slots
  .. ..@ left     : num [1:22132] 0 0.281 0.54 0.754 0.909 ...
  .. ..@ right    : num(0) 
  .. ..@ stereo   : logi FALSE
  .. ..@ samp.rate: num 22050
  .. ..@ bit      : num 16
  .. ..@ pcm      : logi TRUE
 $ :Formal class 'Wave' [package "tuneR"] with 6 slots
  .. ..@ left     : num [1:44265] 0 0 0 0 0 0 0 0 0 0 ...
  .. ..@ right    : num(0) 
  .. ..@ stereo   : logi FALSE
  .. ..@ samp.rate: num 22050
  .. ..@ bit      : num 16
  .. ..@ pcm      : logi TRUE
 $ :Formal class 'Wave' [package "tuneR"] with 6 slots
  .. ..@ left     : num [1:22133] -0.997 -0.979 -0.883 -0.715 -0.49 ...
  .. ..@ right    : num(0) 
  .. ..@ stereo   : logi FALSE
  .. ..@ samp.rate: num 22050
  .. ..@ bit      : num 16
  .. ..@ pcm      : logi TRUE