voice vignette - The R part

version 0.2.6

Filipe J. Zabala

2021-11-08 08:48:03

0. Installation

https://github.com/filipezabala/voice

1. Extract features

Load packages

# packs
library(voice)
library(tidyverse)
library(music)
library(gm)

Setting directories and removing old ones

dirs <- c('vaDir', 'wavDir', 'mp3Dir', 'musicxmlDir')
vaDir <- '~/Downloads/voiceAudios'
for(i in 1:length(dirs)){
  if(i>1){ assign(dirs[i], paste0(get(dirs[1]), '/', dirs[i])) }
  ifelse(!dir.exists(get(dirs[i])), dir.create(get(dirs[i])), 'Directory exists!')
}
cmd <- paste0('rm ', wavDir, '/*.*; ', 'rm ', mp3Dir, '/*.*')
system(cmd)

Get audio

url0 <- 'https://github.com/filipezabala/voiceAudios/blob/main/mp3/doremi.mp3?raw=true'
download.file(url0, paste0(mp3Dir, '/doremi.mp3'), mode = 'wb')
embedr::embed_audio(url0)

Convert mp3 to wav mono

cmd <- 'cd ~/Downloads/voiceAudios/mp3Dir;
for i in *.[Mm][Pp]3; do ffmpeg -i "$i" -ac 1 "../wavDir/${i%.*}.wav"; done'
system(cmd)

Extract features

ef <- voice::extract_features(wavDir, features = c('f0','gain'),
                              round.to = 6, windowShift = 5)
#> PROGRESS 100% 
#> FILE 1 OF 1 | 0.006 SECONDS
#> 
#> TOTAL TIME 0.418 SECONDS
ef
#> # A tibble: 1,179 × 5
#>    id_seq id_seq_file file_name_ext    F0  GAIN
#>     <int>       <int> <chr>         <dbl> <dbl>
#>  1      1           1 doremi.wav       NA  16.8
#>  2      2           2 doremi.wav       NA  18.5
#>  3      3           3 doremi.wav       NA  18.4
#>  4      4           4 doremi.wav       NA  17.5
#>  5      5           5 doremi.wav       NA  17.2
#>  6      6           6 doremi.wav       NA  17.1
#>  7      7           7 doremi.wav       NA  16.7
#>  8      8           8 doremi.wav       NA  16.3
#>  9      9           9 doremi.wav       NA  16.2
#> 10     10          10 doremi.wav       NA  16.3
#> # … with 1,169 more rows

2. Smooth

odd <- seq(1,11,2)
ef_sm <- vector('list', length(odd))
names(ef_sm) <- paste0('k=', odd)
for(i in 1:length(ef_sm)){
  ef_sm[[i]] <- voice::smooth_df(ef, id = 3, k = i)
}
sapply(ef_sm, dim)
#>       k=1  k=3  k=5  k=7  k=9 k=11
#> [1,] 1179 1178 1177 1176 1175 1174
#> [2,]    5    5    5    5    5    5

Plot F0 smoothing

par(mfrow = c(2,3))
for(i in 1:length(ef_sm)){
  plot(ef_sm[[i]]$F0, main = paste0('k = ', odd[i]))
}

3. Assign notes

Assign notes in Scientific Pitch Notation to F0.

for(i in 1:length(ef_sm)){
  ef_sm[[i]]$F0_spn <- voice::notes(ef_sm[[i]]$F0)
}

4. Duration

dur_spn <- vector('list', length(ef_sm))
names(dur_spn) <- paste0('k=', odd)
for(i in 1:length(ef_sm)){
  dur_spn[[i]] <- voice::duration(ef_sm[[i]]$F0_spn) 
}

5. Music sheet

Compress to 1%

# compress
ef_01 <- voice::conv_df(ef, 0.01, id = 3)

# assign notes
ef_01$F0_spn <- voice::notes(ef_01$F0, measure = 'spn')

# duration
nd_01 <- voice::duration(ef_01$F0_spn)

# gm by Renfei Mao
m01 <- gm::Music()
m01 <- m01 +
  gm::Meter(4, 4) +
  gm::Line(pitches = as.list(as.character(nd_01$note)),
           durations = as.list(nd_01$dur_line)) +
  Tempo(170)
show(m01, to = c('score', 'audio'))