voice vignette

version 0.0.0.9033

Filipe J. Zabala

2021-08-15

Installation

https://github.com/filipezabala/voice

Example 1

Find frequencies, notes and durations. Play and get sheet music.

Load packages

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

Set directories

The split directory will be used in Example 2.

vaDir <- '~/Downloads/voiceAudios'
wavDir <- paste0(vaDir, '/wav')
rttmDir <- paste0(vaDir, '/rttm')
splitDir <- paste0(vaDir, '/split')
mxmlDir <- paste0(vaDir, '/musicxml')
ifelse(!dir.exists(vaDir), dir.create(vaDir), 'Directory exists!')
#> [1] TRUE
ifelse(!dir.exists(wavDir), dir.create(wavDir), 'Directory exists!')
#> [1] TRUE
ifelse(!dir.exists(rttmDir), dir.create(rttmDir), 'Directory exists!')
#> [1] TRUE
ifelse(!dir.exists(splitDir), dir.create(splitDir), 'Directory exists!')
#> [1] TRUE
ifelse(!dir.exists(mxmlDir), dir.create(mxmlDir), 'Directory exists!')
#> [1] TRUE

Get audios

url0 <- 'https://github.com/filipezabala/voiceAudios/raw/main/wav/bebezinho_2.005.wav'
download.file(url0, paste0(wavDir, '/bebezinho_2.005.wav'), mode = 'wb')

Extract features

ef <- voice::extract_features(wavDir, features = c('f0','formants','gain'),
                              round.to = 6, windowShift = 5)
#> PROGRESS 100% 
#> FILE 1 OF 1 | 0.001 SECONDS
#> 
#> TOTAL TIME 0.676 SECONDS
ef
#> # A tibble: 400 × 11
#>    file_name            F0    F1    F2    F3    F4    F5    F6    F7    F8  GAIN
#>    <chr>             <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#>  1 bebezinho_2.005.…  156.   323  1658  2940    NA  4302  5306  6257  7221  51.8
#>  2 bebezinho_2.005.…  158.   299  1843    NA  3085  4196  5262  6209  7219  48.9
#>  3 bebezinho_2.005.…  160.   297  1838  1878  3137  4111  5074  6129  7238  41.3
#>  4 bebezinho_2.005.…  159.   302  1814  2080  3135  4096  4539  6222  7268  29.7
#>  5 bebezinho_2.005.…  158.   304  1902  1964  3100  4125  4431  6255  7281  25.0
#>  6 bebezinho_2.005.…  153.   303  1660  2027  3068  4180  4267  6304  7301  25.1
#>  7 bebezinho_2.005.…  151.   300  1672  1988  3087  4051  4190  6287  7267  26.0
#>  8 bebezinho_2.005.…  148.   295  1644  1922  3100  4155    NA  6245  7187  27.0
#>  9 bebezinho_2.005.…  145.   294  1927  3101  3904  4178    NA  6221  7163  27.3
#> 10 bebezinho_2.005.…  145.   298  1937    NA  3102  4189    NA  6080  7181  26.5
#> # … with 390 more rows

Pooling

(ef01 <- voice::conv_df(ef, .01)) # 1%
#> # A tibble: 4 × 11
#>   file_name             F0    F1    F2    F3    F4    F5    F6    F7    F8  GAIN
#>   <chr>              <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 bebezinho_2.005.w…  156.   323  1658  2940 3085   4302  5306  6257  7221  51.8
#> 2 bebezinho_2.005.w…  171.   220  2016  2871 4007.  4806  5481  5989  7415  36.0
#> 3 bebezinho_2.005.w…  272.   278  1648  2495 3264.  4342  5566  6159  7088  29.6
#> 4 bebezinho_2.005.w…  228.   526   907  2492 3469   4140  5404  6596  7208  40.4

Assign notes

spn <- lapply(ef01[2:10], voice::notes)
spn <- bind_rows(spn)
colnames(spn) <- paste0('spn_', colnames(spn))
ef01 <- bind_cols(ef01, spn)

midi <- lapply(ef01[2:10], voice::notes, method = 'midi')
midi <- bind_rows(midi)
colnames(midi) <- paste0('midi_', colnames(midi))
ef01 <- bind_cols(ef01, midi)
glimpse(ef01)
#> Rows: 4
#> Columns: 29
#> $ file_name <chr> "bebezinho_2.005.wav", "bebezinho_2.005.wav", "bebezinho_2.0…
#> $ F0        <dbl> 155.8304, 171.0694, 271.5151, 227.8872
#> $ F1        <dbl> 323, 220, 278, 526
#> $ F2        <dbl> 1658, 2016, 1648, 907
#> $ F3        <dbl> 2940, 2871, 2495, 2492
#> $ F4        <dbl> 3085.000, 4006.667, 3264.000, 3469.000
#> $ F5        <dbl> 4302, 4806, 4342, 4140
#> $ F6        <dbl> 5306, 5481, 5566, 5404
#> $ F7        <dbl> 6257, 5989, 6159, 6596
#> $ F8        <dbl> 7221, 7415, 7088, 7208
#> $ GAIN      <dbl> 51.80362, 35.98599, 29.56570, 40.36103
#> $ spn_F0    <ord> D#3, F3, C#4, A#3
#> $ spn_F1    <ord> E4, A3, C#4, C5
#> $ spn_F2    <ord> G#6, B6, G#6, A#5
#> $ spn_F3    <ord> F#7, F7, D#7, D#7
#> $ spn_F4    <ord> G7, B7, G#7, A7
#> $ spn_F5    <ord> C8, D8, C#8, C8
#> $ spn_F6    <ord> E8, F8, F8, E8
#> $ spn_F7    <ord> G8, F#8, G8, G#8
#> $ spn_F8    <ord> A8, A#8, A8, A8
#> $ midi_F0   <int> 51, 53, 61, 58
#> $ midi_F1   <int> 64, 57, 61, 72
#> $ midi_F2   <int> 92, 95, 92, 82
#> $ midi_F3   <int> 102, 101, 99, 99
#> $ midi_F4   <int> 103, 107, 104, 105
#> $ midi_F5   <int> 108, 110, 109, 108
#> $ midi_F6   <int> 112, 113, 113, 112
#> $ midi_F7   <int> 115, 114, 115, 116
#> $ midi_F8   <int> 117, 118, 117, 117

Distance (in semitones)

nd.spn <- music::noteDistance(as.character(ef01$spn_F0))
table(nd.spn) # semitones
#> nd.spn
#> -3  0  2  8 
#>  1  1  1  1

Get duration

dur.spn <- voice::duration(ef01$spn_F0)
dur.midi <- voice::duration(ef01$midi_F0)

Play

music::playNote(note = as.character(dur.spn$note),
                duration = dur.spn$dur_line)

Partiture

m <- gm::Music()
m <- m +
  # add a 4/4 time signature
  gm::Meter(4, 4) +
  # manually adding midi notes
  gm::Line(pitches = list(51, 53, 61, 58),
       durations = list(1,1,1,1))
m
#> Music
#> 
#> Line 1
#> 
#> * as part 1 staff 1 voice 1
#> * of length 4
#> * of pitches 51, 53, 61, 58
#> * of durations 1, 1, 1, 1
#> 
#> Meter 4/4
export(m, mxmlDir, 'bebezinho', 'musicxml')

Just play ‘bebezinho.musicxml’ using MuseScore!

Example 2

Cut audios.

Get audios

# font url
url0 <- 'https://github.com/filipezabala/voiceAudios/raw/main/mp3/'

# mp3 files
mp3Files <- c('anthem0.mp3', 'anthem1.mp3', 'anthem2.mp3',
              'game0.mp3', 'game1.mp3', 'game2.mp3',
              'phantom0.mp3', 'phantom1.mp3',  'phantom2.mp3',
              'romeo0.mp3', 'romeo1.mp3', 'romeo2.mp3',
              'sherlock0.mp3', 'sherlock1.mp3', 'sherlock2.mp3',
              'war0.mp3', 'war1.mp3', 'war2.mp3')

# downloading just the first mp3 file (remove [1] to download all)
for(i in mp3Files[1]){
  system(paste0('wget -r -np -k ', url0, i, ' -P ~/Downloads/voiceAudios/mp3'))
}

# tidying up files and directories
system('cp ~/Downloads/voiceAudios/mp3/github.com/filipezabala/voiceAudios/raw/main/mp3/*.* ~/Downloads/voiceAudios/mp3')
system('rm -rf ~/Downloads/voiceAudios/mp3/github.com/')

Removing old files

cmd <- paste0('rm ', wavDir, '/*.*')
system(cmd)

Converting mp3 to wav

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

Poetry

The best words in their best order. Takes around the audio time at 8CPU and the double of the audio time at 4CPU.

voice::poetry(wavDir, to = rttmDir, pycall = '~/miniconda3/envs/pyvoice38/bin/python3.8')
#> Time difference of 57.39239 secs

Split wave

# split wave
ini <- Sys.time()
voice::splitw(wavDir, fromRttm = rttmDir, to = splitDir)
Sys.time()-ini
#> Time difference of 0.3020289 secs

To do