Skip to content

Commit d8ed93e

Browse files
author
klaus
committed
* Renamed create_from_irb and create_from wjd_db
* Introduced parkr_options, printing controlled by debug options (defaults to FALSE now) * Added some exports for some usefull util functions * Added simulate_wjd to simulate solos from the WJD with matching chorusses and tempo * Added handling of NC chords, solved for the time being by inserting random chords, sampled from the WJD * Added missing chord_definitions (minb6, 6)
1 parent 150ff5b commit d8ed93e

26 files changed

+347
-63
lines changed

NAMESPACE

+10-2
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,24 @@
22

33
export(chorus_to_mcsv2)
44
export(cpc_plot_solo)
5-
export(create_from_irb)
6-
export(create_sheet)
5+
export(create_leadsheet)
6+
export(create_leadsheet_from_chord_db)
7+
export(create_leadsheet_from_irb)
8+
export(create_leadsheet_from_wjd_db)
79
export(find_wba)
810
export(find_wba_by_phrase)
11+
export(freq2_table)
12+
export(freq_table)
913
export(generate_solo)
1014
export(key_analysis)
1115
export(make_many_solos)
16+
export(parkr_options)
1217
export(parse_chord)
1318
export(phrase_to_mcsv2)
1419
export(piano_roll)
20+
export(pull_unique)
21+
export(signed_modulo)
22+
export(simulate_wjd)
1523
export(solo_to_mcsv2)
1624
export(write_mcsv2)
1725
import(dplyr)

NEWS.md

+9
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
# parkR 0.3.0
2+
3+
* Renamed create_from_irb and create_from wjd_db
4+
* Introduced parkr_options, printing controlled by debug options (defaults to FALSE now)
5+
* Added some exports for some usefull util functions
6+
* Added simulate_wjd to simulate solos from the WJD with matching chorusses and tempo
7+
* Added handling of NC chords, solved for the time being by inserting random chords, sampled from the WJD
8+
* Added missing chord_definitions (minb6, 6)
9+
110
# parkR 0.2.1
211

312
Added basic features, transforms, and metadata for WJD, Omnibook and Essen Folks Song Collection

R/bigram_stack.R

-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
library(tidyverse)
2-
printf <- function(...) print(sprintf(...))
3-
messagef <- function(...) message(sprintf(...))
42

53
bigram_encoder <- function(x, level = 1, sep = ""){
64
#if(is.character(x)){

R/chords.R

+117-20
Original file line numberDiff line numberDiff line change
@@ -66,17 +66,32 @@ chord_definitions[["maj7"]][["scale_weights"]] <- c(1.0, 0.0, 0.0)
6666
chord_definitions[["maj7"]][["arpeggio"]] <- c(-12, -8, -5, -1, 0, 4, 7, 11, 12 + 2, 12 + 6, 12 + 9)
6767

6868
chord_definitions[["maj"]] <- chord_definitions[["maj7"]]
69+
chord_definitions[["6"]] <- chord_definitions[["maj7"]]
70+
6971
chord_definitions[["min7"]][["scales"]] <- list("dorian" = dorian,
7072
"aeolian" = aeolian,
7173
"melodic_minor" = melodic_minor,
7274
"harmonic_minor" = harmonic_minor,
7375
"min_7_tetra" = min_7_tetra)
74-
#chord_definitions[["min7"]][["scale_weights"]] <- c(.7, .2, .05, .05)
7576
chord_definitions[["min7"]][["scale_weights"]] <- c(1., 0.0, 0.0, 0.0, 0.0)
7677
chord_definitions[["min7"]][["arpeggio"]] <- c(-12, -9, -5, -2, 0, 3, 7, 10, 12 + 2, 12 + 5, 12 + 9)
7778

7879
chord_definitions[["min"]] <- chord_definitions[["min7"]]
7980

81+
chord_definitions[["minb6"]][["scales"]] <- list("aeolian" = aeolian,
82+
"harmonic_minor" = harmonic_minor)
83+
chord_definitions[["minb6"]][["scale_weights"]] <- c(1., 0.0)
84+
chord_definitions[["minb6"]][["arpeggio"]] <- c(-12, -9, -5, -3, 0, 3, 7, 8, 12 + 2, 12 + 5)
85+
86+
chord_definitions[["min6"]][["arpeggio"]] <- c(-12, -9, -5, -4, 0, 3, 7, 9, 12, 12 + 3)
87+
chord_definitions[["min6"]][["scales"]] <- list("dorian" = dorian)
88+
chord_definitions[["min6"]][["scale_weights"]] <- c(1.0)
89+
90+
chord_definitions[["minmaj7"]][["arpeggio"]] <- c(-12, -9, -5, -1, 0, 3, 7, 11, 12, 12 + 3)
91+
chord_definitions[["minmaj7"]][["scales"]] <- list("harmonic_minor" = harmonic_minor)
92+
chord_definitions[["minmaj7"]][["scale_weights"]] <- c(1.0)
93+
94+
8095
chord_definitions[["7"]][["scales"]] <- list("mixolydian" = mixolydian,
8196
"mixolydian_sharp11" = mixolydian_sharp11,
8297
"altered" = altered,
@@ -101,14 +116,8 @@ chord_definitions[["o7"]][["scales"]] <- list("gtht" = gtht,
101116
"dom_blues" = (major_blues + 6) %% 12)
102117
#chord_definitions[["o7"]][["scale_weights"]] <- c(.8, .2)
103118
chord_definitions[["o7"]][["scale_weights"]] <- c(1.0, 0.0, 0.0, 0.0)
119+
chord_definitions[["o"]] <- chord_definitions[["o7"]]
104120

105-
chord_definitions[["min6"]][["arpeggio"]] <- c(-12, -9, -5, -4, 0, 3, 7, 9, 12, 12 + 3)
106-
chord_definitions[["min6"]][["scales"]] <- list("dorian" = dorian)
107-
chord_definitions[["min6"]][["scale_weights"]] <- c(1.0)
108-
109-
chord_definitions[["minmaj7"]][["arpeggio"]] <- c(-12, -9, -5, -1, 0, 3, 7, 11, 12, 12 + 3)
110-
chord_definitions[["minmaj7"]][["scales"]] <- list("harmonic_minor" = harmonic_minor)
111-
chord_definitions[["minmaj7"]][["scale_weights"]] <- c(1.0)
112121

113122
chord_types <- c("minmaj7", "maj7", "min7", "min6","minb6", "min", "maj", "m7b5", "o7", "o", "7", "6")
114123
extensions <- c("add9", "add3", "sus", "b5", "alt", "\\+", "9b", "9#", "9", "11#", "11", "13b", "13" )
@@ -167,7 +176,7 @@ tone_name_to_pc <- Vectorize(function(tone){
167176
pc <- sharp_pc -1
168177
}
169178
else {
170-
message(sprintf("Invalid tone %s", tone))
179+
messagef("Invalid tone %s", tone)
171180
stop()
172181
return(NA)
173182
}
@@ -261,7 +270,7 @@ parse_chord <- function(chord_label){
261270
}
262271
else {
263272
messagef("Parsing %s", chord_label)
264-
message(sprintf("Unknown chord type in %s", chord_label))
273+
messagef("Unknown chord type in %s", chord_label)
265274
stop()
266275
return(NULL)
267276
}
@@ -308,6 +317,9 @@ find_best_match_to_chord <- function(int_vector, start_pitch, chord, max_transpo
308317
int_vector <- value_to_vec(int_vector)
309318
}
310319
tmp <- get_scale_pitches(chord, sample = F, return_weights = T)
320+
if(is.null(tmp)){
321+
return(integer(0))
322+
}
311323
scales <- tmp$scales
312324
scale_weights <- tmp$weights
313325
best_trans <- max_transposition + 1
@@ -335,6 +347,9 @@ weighted_sample <- function(sample_set, weights, size = 1){
335347
w <- as.integer(round(weights / sum(weights) * 100))
336348
#print(w)
337349
#print(sample_set)
350+
if(is.null(sample_set)){
351+
browser()
352+
}
338353
if(is.null(names(sample_set))){
339354
names(sample_set) <- 1: length(sample_set)
340355
}
@@ -358,6 +373,11 @@ get_scale_pitches <- function(chord, min_pitch = 48, max_pitch = 84, sample = T,
358373
return(NULL)
359374
}
360375
}
376+
if(chord$type == "NC"){
377+
message("[get_scale_pitches] Found NC chord")
378+
return(NULL)
379+
}
380+
361381
#print(chord)
362382
for(i in 1:nrow(chord)){
363383
ct <- chord[i, ]$type
@@ -455,24 +475,35 @@ unroll_durations <- function(durations){
455475
tmp
456476
}
457477

458-
#' create_from_irb
478+
#' create_leadhseet_chord_db
459479
#'
460-
#' This function generates a lead sheet data from parsed iRealBook data (irb),
480+
#' This function generates a lead sheet data from parsed chord data frame (irb or wjd_chord_db),
461481
#'
462-
#' @param compid (integer or character scalar) If integer, then id of lead sheet in the iRealBook data (data(irb)), if character, than title of song
482+
#' @param db (chord data frame) Chord data frame to use
483+
#' @param compid (integer or character scalar) If integer, then id of lead sheet in the chord data, if character, than title of song
463484
#' @param name (character scalar) Currently unused
464485
#' @param with_form (logical scalar) Flag if form shall be added
465486
#' @return A leed sheet data frame
466487
#' @export
467-
create_from_irb <- function(compid, name = NULL, with_form = F){
488+
create_leadsheet_from_chord_db <- function(db, compid, name = NULL, with_form = F){
468489
if(is.character(compid)){
469-
sheet <- parkR::irb[tolower(parkR::irb$title) == tolower(compid),] %>%
490+
sheet <- db %>% filter(tolower(title) == tolower(!!compid)) %>%
470491
select(chord, duration, section, title, time, composer, date, compid, key)
471492
}
472493
else {
473-
sheet <- parkR::irb[parkR::irb$compid == compid,] %>% select(chord, duration, title, time)
494+
sheet <- db %>% filter(compid == !!compid) %>% select(chord, duration, title, time)
495+
}
496+
if(nrow(sheet) == 1){
497+
return(NULL)
498+
}
499+
if(!nzchar(sheet$time[1])){
500+
time <- c("4", "4")
501+
}
502+
else{
503+
time <- strsplit(sheet$time[1], "/")[[1]]
504+
474505
}
475-
time <- strsplit(sheet$time[1], "/")[[1]]
506+
#browser()
476507
period <- as.integer(time[1])
477508
denom <- as.integer(time[2])
478509
if(period == 6 && denom == 8){
@@ -486,7 +517,6 @@ create_from_irb <- function(compid, name = NULL, with_form = F){
486517
mutate(length_ticks = duration * ticks_per_beat) %>%
487518
mutate(parsed = purrr::map(chord, parse_chord)) %>%
488519
tidyr::unnest(cols = parsed)
489-
490520
sheet$onset_ticks <- unroll_durations(sheet$length_ticks)
491521
sheet$running_beat <- unroll_durations(sheet$duration)
492522
sheet$beat <- (sheet$running_beat %% period ) + 1
@@ -504,7 +534,37 @@ create_from_irb <- function(compid, name = NULL, with_form = F){
504534
sheet %>% set_format("lead_sheet")
505535
}
506536

507-
#' create_sheet
537+
538+
#' create_leadsheet_from_irb
539+
#'
540+
#' This function generates a lead sheet data from parsed iRealBook data (irb),
541+
#'
542+
#' @param compid (integer or character scalar) If integer, then id of lead sheet in the iRealBook data (data(irb)), if character, than title of song
543+
#' @param name (character scalar) Currently unused
544+
#' @param with_form (logical scalar) Flag if form shall be added
545+
#' @return A leed sheet data frame
546+
#' @export
547+
create_leadsheet_from_irb <- function(compid, name = NULL, with_form = F){
548+
create_leadsheet_from_chord_db(parkR::irb, compid, name, with_form)
549+
}
550+
551+
#' create_leadsheet_from_wjd_db
552+
#'
553+
#' This function generates a lead sheet data from parsed WJD chord data (wjd_chord_db),
554+
#'
555+
#' @param compid (integer or character scalar) If integer, then id of lead sheet in the iRealBook data (data(irb)), if character, than title of song
556+
#' @param name (character scalar) Currently unused
557+
#' @param with_form (logical scalar) Flag if form shall be added
558+
#' @return A leed sheet data frame
559+
#' @export
560+
create_leadsheet_from_wjd_db <- function(compid, name = NULL, with_form = F){
561+
db <- parkR::wjd_chord_db %>%
562+
rename(chord = original) %>%
563+
left_join(parkR::wjd_meta %>% select(title, id, time = signature), by = "id")
564+
create_leadsheet_from_chord_db(db, compid, name, with_form)
565+
}
566+
567+
#' create_leadsheet
508568
#'
509569
#' This function generates a lead sheet data frame from a vector of chord symbols and beat lengths per chord
510570
#'
@@ -513,7 +573,7 @@ create_from_irb <- function(compid, name = NULL, with_form = F){
513573
#' @param length_beats (integer scalar) length of chord in beats
514574
#' @return A leed sheet data frame
515575
#' @export
516-
create_sheet <- function(name, chords, length_beats){
576+
create_leadsheet <- function(name, chords, length_beats){
517577
tmp <- tibble(chord = chords,
518578
length_beats = length_beats)
519579
tmp <- tmp %>% mutate(length_ticks = length_beats * 4) %>%
@@ -526,6 +586,37 @@ create_sheet <- function(name, chords, length_beats){
526586
tmp %>% set_format("lead_sheet")
527587
}
528588

589+
#' simulate_wjd
590+
#'
591+
#' This function simulates a full Weimar Jazz Database, based on lead sheet, chorus counts and tempo
592+
#'
593+
#' @param ids (integer vector) List of ids to create, ids shoudl be in the range 1 to 456, everything else will be ignored
594+
#' @return A data frame of generated solos
595+
#' @export
596+
simulate_wjd <- function(ids = 1:456){
597+
wjd_meta <- parkR::wjd_meta %>% mutate(compid = as.integer(factor(id)))
598+
ids <- as.integer(ids)
599+
ids <- ids[ids >= 1 ] & ids[ids <= 456 ]
600+
map_dfr(ids, function(cid) {
601+
#messagef("Generating %d...", cid)
602+
sheet <- create_leadsheet_from_wjd_db(compid = cid)
603+
if(!is.null(sheet)){
604+
md <- wjd_meta %>% filter(compid == cid)
605+
message(sprintf("(%d): Generating %s with %d choruses", cid, md$id, md$chorus_count))
606+
solo <- generate_solo(sheet, n_chorus = md$chorus_count, tempo = round(md$avgtempo))
607+
if(!is.null(solo)){
608+
solo <- solo %>%
609+
mutate(id = md$id,
610+
# compid = md$compid,
611+
# title = md$title,
612+
# n_chorus = md$chorus_count,
613+
# tempo = round(md$avgtempo),
614+
.before = 1)
615+
}
616+
solo
617+
}
618+
})
619+
}
529620
parse_wjd_bar <- function(bar_chords, bar_number = 1){
530621
#print(bar_chords)
531622
elements <- strsplit(bar_chords, " ")[[1]]
@@ -598,6 +689,7 @@ signed_mod <- function(x, n = 12){
598689
r[which(r > n/2)] <- r[which(r > n/2)] - n
599690
r
600691
}
692+
601693
create_sheet_from_wjd_changes <- function(changes, form_parts = NULL){
602694
purrr::map2_dfr(changes$chord_changes,
603695
changes$id,
@@ -616,6 +708,11 @@ create_sheet_from_wjd_changes <- function(changes, form_parts = NULL){
616708

617709
}
618710

711+
#' export
712+
get_random_chord <- function(chord_db = parkR::irb){
713+
sprintf("%s%s", sample(chord_db$root, 1), sample(chord_db$type, 1))
714+
}
715+
619716
expand_chord_changes <- function(split_changes, num_choruses = 1, max_bar = NULL, with_key_analysis = T){
620717
n_ids <- length(unique(split_changes$id))
621718
if(n_ids > 1){

R/data.R

+8-8
Original file line numberDiff line numberDiff line change
@@ -14,57 +14,57 @@ NULL
1414

1515
#' WJD chords
1616
#'
17-
#' Chord changes /lead sheets extracted from the Weimar Jazz Database
17+
#' Chord changes & lead sheets extracted from the Weimar Jazz Database
1818
#' @name wjd_chord_db
1919
#' @docType data
2020
NULL
2121

2222
#' WBA_df
2323
#'
24-
#' Database of WBA atoms
24+
#' Database of WBA atoms extracted from the Weimar Jazz Database.
2525
#' @name WBA_df
2626
#' @docType data
2727
NULL
2828

2929
#' wba_mla
3030
#'
31-
#' Database of WBA atoms and midlevel units (MLUs)
31+
#' Database of WBA atoms and midlevel units (MLUs) extracted from the Weimar Jazz Database
3232
#' @name wba_mla
3333
#' @docType data
3434
NULL
3535

3636

3737
#' successor_dist
3838
#'
39-
#' First order Markov transitions of WBA atoms
39+
#' First order Markov transitions of WBA atoms extracted from the Weimar Jazz Database
4040
#' @name successor_dist
4141
#' @docType data
4242
NULL
4343

4444
#' succ_ioiclass
4545
#'
46-
#' First order Markov transitions of interonset interval classes
46+
#' First order Markov transitions of interonset interval classes extracted from the Weimar Jazz Database
4747
#' @name succ_ioiclass
4848
#' @docType data
4949
NULL
5050

5151
#' phrase_begin_dist
5252
#'
53-
#' Distribution of WBA atoms at beginning of phrases
53+
#' Distribution of WBA atoms at beginning of phrases extracted from the Weimar Jazz Database
5454
#' @name phrase_begin_dist
5555
#' @docType data
5656
NULL
5757

5858
#' length_dist
5959
#'
60-
#' Disbtribution of number of phrases over WJD solos
60+
#' Disbtribution of number of phrases over WJD solos extracted from the Weimar Jazz Database
6161
#' @name length_dist
6262
#' @docType data
6363
NULL
6464

6565
#' phrase_length_dist
6666
#'
67-
#' Disbtribution of phrase lengths and relative phrase positions
67+
#' Disbtribution of phrase lengths and relative phrase positions extracted from the Weimar Jazz Database
6868
#' @name phrase_length_dist
6969
#' @docType data
7070
NULL

R/interval_grammar.R

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
library(tidyverse)
22

3-
messagef <- function(...) message(sprintf(...))
43
printf <- function(...) print(sprintf(...))
4+
messagef <- function(...) if(parkR::parkr_options()$debug) message(sprintf(...))
55

66
value_to_vec <- function(value_str){
77
vec <- gsub("\\[", "", as.character(value_str))

0 commit comments

Comments
 (0)