├── LICENSE ├── .Rbuildignore ├── data ├── chords.RData └── chords.csv ├── .gitignore ├── images └── G_Major.png ├── tests ├── testthat.R ├── testthat │ ├── test_scales.R │ └── test_chords.R └── test_tablature.R ├── NAMESPACE ├── NEWS.md ├── cran-comments.md ├── ggguitar.Rproj ├── man ├── narrow_chord.Rd ├── chord_for_frets.Rd ├── select_chords.Rd ├── notes_for_frets.Rd ├── tablature.Rd └── chords.Rd ├── README.md ├── DESCRIPTION ├── R ├── data.R └── guitar_chords.R └── vignettes └── my-vignette.Rmd /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2016 2 | COPYRIGHT HOLDER: Casimir Saternos 3 | -------------------------------------------------------------------------------- /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | images 4 | cran-comments.md 5 | -------------------------------------------------------------------------------- /data/chords.RData: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ezgraphs/ggguitar/HEAD/data/chords.RData -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | .Ruserdata 5 | inst/doc 6 | *.png 7 | -------------------------------------------------------------------------------- /images/G_Major.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ezgraphs/ggguitar/HEAD/images/G_Major.png -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(ggguitar) 3 | 4 | test_check("ggguitar") 5 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(chord_for_frets) 4 | export(notes_for_frets) 5 | export(select_chords) 6 | export(tablature) 7 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # News 2 | 3 | ## 0.1.1 4 | * (Issue #1) Provide example of left handed chord in vignette. 5 | * (Issue #2) Set versions of dependencies. 6 | * (Issue #3) Did not fix, but added example of scales to vignette to clarify package scope/usage. 7 | * (Issue #4) Add arg to set label size 8 | 9 | ## 0.0.1 Initial Release 10 | -------------------------------------------------------------------------------- /cran-comments.md: -------------------------------------------------------------------------------- 1 | ## Test environments 2 | ## R version 3.3.2 (2016-10-31) 3 | ## Platform: x86_64-apple-darwin13.4.0 (64-bit) 4 | ## Running under: OS X El Capitan 10.11.6 5 | 6 | ## R CMD check results 7 | There were no ERRORs. 8 | 9 | There were WARNINGs... mostly relating to masked dependencies. 10 | 11 | ## Other Notes 12 | 13 | * Thank you for your patience as I address issues. Submission contains only Minor changes from 1.1. 14 | -------------------------------------------------------------------------------- /ggguitar.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: knitr 13 | LaTeX: pdfLaTeX 14 | 15 | AutoAppendNewline: Yes 16 | StripTrailingWhitespace: Yes 17 | 18 | BuildType: Package 19 | PackageUseDevtools: Yes 20 | PackageInstallArgs: --no-multiarch --with-keep.source 21 | PackageRoxygenize: rd,collate,namespace 22 | -------------------------------------------------------------------------------- /tests/testthat/test_scales.R: -------------------------------------------------------------------------------- 1 | context("Testing Scales") 2 | 3 | G_M_scale <- c(3, 0, 0, 0, NA, NA, 4 | NA, 2, 2, NA, NA, NA, 5 | NA, 3, 4, NA, NA, NA) 6 | 7 | C_M_scale <- c(NA, NA, 0, 0, 0, NA, 8 | NA, NA, 2, 2, 1, NA, 9 | NA, 3, 3, NA, NA, NA) 10 | 11 | test_that("Major scale matches notes", { 12 | expect_equal(notes_for_frets(G_M_scale), 13 | c("g", "a", "b", "c", "d", "e", "f#", "g")) 14 | 15 | expect_equal(notes_for_frets(C_M_scale), 16 | c("c", "d", "e", "f", "g", "a", "b", "c")) 17 | }) 18 | -------------------------------------------------------------------------------- /man/narrow_chord.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/guitar_chords.R 3 | \name{narrow_chord} 4 | \alias{narrow_chord} 5 | \title{Narrow (Filter) Chord Selection} 6 | \usage{ 7 | narrow_chord(chords, value, name) 8 | } 9 | \arguments{ 10 | \item{chords}{A data frame of chords.} 11 | 12 | \item{value}{The value to be filtered.} 13 | 14 | \item{name}{The name to be filtered.} 15 | } 16 | \value{ 17 | Returns a data frame of chords. 18 | } 19 | \description{ 20 | This function filters rows in the chord data frame 21 | by criteria passed in and accounts for nulls. 22 | The nifty bit is - given a full set of chords, you can get chords that 23 | use a given fret or frets. 24 | } 25 | 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ggguitar 2 | 3 | [![](http://cranlogs.r-pkg.org/badges/ggguitar)](https://CRAN.R-project.org/package=ggguitar) 4 | 5 | Latest release available from [CRAN](https://cran.r-project.org/web/packages/ggguitar/index.html). 6 | 7 | ## Description 8 | Create Guitar Tablature and related documentation. Powered by ggplot2 and the Tidyverse. 9 | 10 | ## Example Usage 11 | ``` 12 | > library(ggguitar) 13 | > chord_GM <- c(3, 2, 0, 0, 0, 3) 14 | > tablature('G Major', chord_GM) 15 | ``` 16 | 17 | ![alt text](images/G_Major.png "G Major") 18 | 19 | ``` 20 | > chord_for_frets(chord_GM) 21 | [1] "g" "b" "d" "g" "b" "g" 22 | ``` 23 | 24 | See the [Vignette](https://cran.r-project.org/web/packages/ggguitar/vignettes/my-vignette.html) for more examples. 25 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: ggguitar 2 | Type: Package 3 | Title: Utilities for Creating Guitar Tablature 4 | Version: 0.1.1 5 | Authors@R: person("Casimir", "Saternos", email="cas.saternos@gmail.com", role = c('aut','cre')) 6 | Maintainer: Casimir Saternos 7 | Description: Utilities for Creating Guitar Tablature using tidyverse packages. 8 | License: MIT + file LICENSE 9 | LazyData: TRUE 10 | BugReports: https://github.com/ezgraphs/ggguitar/issues 11 | Imports: 12 | dplyr (>= 0.5.0), 13 | ggplot2 (>= 0.2.1.0), 14 | gridExtra(>= 2.2.1), 15 | lazyeval(>= 0.2.0), 16 | readr(>= 1.0.0), 17 | tibble (>= 1.2) 18 | Suggests: 19 | knitr(>= 1.14), 20 | rmarkdown(>= 1.2), 21 | testthat(>= 1.0.2) 22 | RoxygenNote: 5.0.1 23 | VignetteBuilder: knitr 24 | -------------------------------------------------------------------------------- /man/chord_for_frets.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/guitar_chords.R 3 | \name{chord_for_frets} 4 | \alias{chord_for_frets} 5 | \title{Chord for Frets} 6 | \usage{ 7 | chord_for_frets(frets, tuning = c("e", "a", "d", "g", "b", "e")) 8 | } 9 | \arguments{ 10 | \item{frets}{A 6 element vector representing fret positions.} 11 | 12 | \item{tuning}{A 6 element vector representing notes of open strings.} 13 | } 14 | \value{ 15 | Returns a 6 element vector of note names. 16 | } 17 | \description{ 18 | Return the notes for a given set of frets for a specified tuning. 19 | Preserves NAs indicating muted strings. 20 | } 21 | \examples{ 22 | chord_for_frets(c(NA, 3, 2, 0, 1, 0)) 23 | 24 | } 25 | \seealso{ 26 | \code{\link{notes_for_frets}} 27 | } 28 | 29 | -------------------------------------------------------------------------------- /man/select_chords.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/guitar_chords.R 3 | \name{select_chords} 4 | \alias{select_chords} 5 | \title{Select chords by criteria} 6 | \usage{ 7 | select_chords(note_name = NULL, chord_name = NULL, string_1_fret = NULL, 8 | string_2_fret = NULL, string_3_fret = NULL, string_4_fret = NULL, 9 | string_5_fret = NULL, string_6_fret = NULL) 10 | } 11 | \arguments{ 12 | \item{note_name}{Root of the chord.} 13 | 14 | \item{chord_name}{Name of the chord.} 15 | 16 | \item{string_1_fret}{Fret location on the 1st string.} 17 | 18 | \item{string_2_fret}{Fret location on the 2nd string.} 19 | 20 | \item{string_3_fret}{Fret location on the 3rd string.} 21 | 22 | \item{string_4_fret}{Fret location on the 4th string.} 23 | 24 | \item{string_5_fret}{Fret location on the 5th string.} 25 | 26 | \item{string_6_fret}{Fret location on the 6th string.} 27 | } 28 | \value{ 29 | Returns a data frame of chords. 30 | } 31 | \description{ 32 | Select chords by criteria 33 | } 34 | \examples{ 35 | select_chords(chord_name = 'Major', string_5_fret = 3) 36 | select_chords(note='d') 37 | } 38 | 39 | -------------------------------------------------------------------------------- /tests/testthat/test_chords.R: -------------------------------------------------------------------------------- 1 | G_M <- c(3, 2, 0, 0, 0, 3) 2 | C_M <- c(NA, 3, 2, 0, 1, 0) 3 | D_M <- c(NA, NA, 0, 2, 3, 2) 4 | C_M_bar <- c(8, 10, 10, 9, 8, 8) 5 | 6 | context("Testing Chords") 7 | test_that("Major chord matches notes", { 8 | 9 | expect_equal(chord_for_frets(C_M), 10 | c(NA,"c","e","g","c","e")) 11 | 12 | expect_equal(chord_for_frets(G_M), 13 | c("g","b","d","g","b","g")) 14 | 15 | expect_equal(chord_for_frets(D_M), 16 | c(NA,NA,"d","a","d","f#")) 17 | 18 | expect_equal(chord_for_frets(C_M_bar), 19 | c("c","g","c","e","g","c")) 20 | 21 | }) 22 | 23 | test_that("Selected chords are correct", { 24 | 25 | df <- select_chords('g', 'Major') %>% 26 | dplyr::transmute(chord_name=paste(note, chord)) %>% 27 | dplyr::distinct() 28 | expect_equal(df$chord_name, 'g Major') 29 | }) 30 | 31 | test_that("Selected chords include third fret", { 32 | df <- select_chords('g', 'Major', string_5_fret = 3) 33 | expect_equal(paste(df$note, df$chord), 'g Major') 34 | expect_equal(df$string_5_fret, c(3)) 35 | 36 | # df <- select_chords(string_5_fret = 3) 37 | # expect_equal(df$string_5_fret, c(3,3,3,3,3,3)) 38 | }) 39 | -------------------------------------------------------------------------------- /data/chords.csv: -------------------------------------------------------------------------------- 1 | "X1","note","chord","string_1_fret","string_2_fret","string_3_fret","string_4_fret","string_5_fret","string_6_fret","string_1_finger","string_2_finger","string_3_finger","string_4_finger","string_5_finger","string_6_finger" 2 | "1","g","Major", 3, 2,0,0,0,3, 2,1,0,0,0,4 3 | "2","g","Major", 3, 2,0,0,3,3, 2,1,0,0,3,4 4 | "3","c","Major", NA, 3,2,0,1,0, 0,3,2,0,1,0 5 | "4","c","Major 7", NA, 3,2,0,0,0, 0,3,2,0,0,0 6 | "5","c","Major add 9", NA, 3,2,0,3,3, 0,2,1,0,3,4 7 | "6","d","Major", NA,NA,0,2,3,2, 0,0,0,1,3,2 8 | "7","d","Major 7", NA,NA,0,2,2,2, 0,0,0,1,2,3 9 | "8","d","Major 6", NA,NA,0,2,0,2, 0,0,0,1,0,3 10 | "9","d","Dominant 7", NA,NA,0,2,1,2, 0,0,0,1,2,3 11 | "10","d","Major sus 4",NA,NA,0,2,3,3, 0,0,0,1,3,4 12 | "11","d","Major sus 2",NA,NA,0,2,3,0, 0,0,0,1,3,0 13 | "12","a","Major", NA ,0,2,2,2,0, 0,0,2,3,4,0 14 | "13","a","Major 7", NA ,0,2,0,2,0, 0,0,2,0,4,0 15 | "14","e","minor", 0 , 2,2,0,0,0, 0,2,3,0,0,0 16 | "15","e","minor add 9",0 , 2,4,0,0,0, 0,1,3,0,0,0 17 | "16","a","minor", NA ,0,2,2,1,0, 0,0,2,3,1,0 18 | "17","a","minor sus 2",NA ,0,2,2,0,0, 0,0,2,3,0,0 19 | "18","a","minor sus 4",NA ,0,2,2,3,0, 0,0,2,3,4,0 20 | -------------------------------------------------------------------------------- /man/notes_for_frets.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/guitar_chords.R 3 | \name{notes_for_frets} 4 | \alias{notes_for_frets} 5 | \title{This function is similar to \code{\link{chord_for_frets}} but 6 | also handles scales. 7 | Unlike chords_for_frets, this function removes NAs. 8 | This means there are no muted strings identified 9 | if a chord is passed in the frets argument.} 10 | \usage{ 11 | notes_for_frets(frets, tuning = c("e", "a", "d", "g", "b", "e")) 12 | } 13 | \arguments{ 14 | \item{frets}{A vector representing fret positions.} 15 | 16 | \item{tuning}{A 6 element vector representing notes of open strings.} 17 | } 18 | \value{ 19 | Returns a vector of note names. 20 | } 21 | \description{ 22 | This function is similar to \code{\link{chord_for_frets}} but 23 | also handles scales. 24 | Unlike chords_for_frets, this function removes NAs. 25 | This means there are no muted strings identified 26 | if a chord is passed in the frets argument. 27 | } 28 | \examples{ 29 | G_M_scale <- c(3, 0, 0, 0, NA, NA, 30 | NA, 2, 2, NA, NA, NA, 31 | NA, 3, 4, NA, NA, NA) 32 | notes_for_frets(G_M_scale) 33 | 34 | } 35 | \seealso{ 36 | \code{\link{chord_for_frets}} 37 | } 38 | 39 | -------------------------------------------------------------------------------- /R/data.R: -------------------------------------------------------------------------------- 1 | #' A dataset containing chords. 2 | #' 3 | #' A dataset containing chords, their location 4 | #' on a guitar neck, and the standard fingering used 5 | #' to play them. 6 | #' 7 | #' @format A data frame chords: 8 | #' \describe{ 9 | #' \item{X1}{id field} 10 | #' \item{note}{note that is the root of the chord} 11 | #' \item{chord}{name of the chord} 12 | #' \item{string_1_fret}{Which fret should be pressed on the first string.} 13 | #' \item{string_2_fret}{Which fret should be pressed on the second string.} 14 | #' \item{string_3_fret}{Which fret should be pressed on the third string.} 15 | #' \item{string_4_fret}{Which fret should be pressed on the fourth string.} 16 | #' \item{string_5_fret}{Which fret should be pressed on the fifth string.} 17 | #' \item{string_6_fret}{Which fret should be pressed on the sixth string.} 18 | #' \item{string_1_finger}{Which finger should press the specified fret on the first string.} 19 | #' \item{string_2_finger}{Which finger should press the specified fret on the second string.} 20 | #' \item{string_3_finger}{Which finger should press the specified fret on the third string.} 21 | #' \item{string_4_finger}{Which finger should press the specified fret on the fourth string.} 22 | #' \item{string_5_finger}{Which finger should press the specified fret on the fifth string.} 23 | #' \item{string_6_finger}{Which finger should press the specified fret on the sixth string.} 24 | #' } 25 | "chords" 26 | -------------------------------------------------------------------------------- /man/tablature.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/guitar_chords.R 3 | \name{tablature} 4 | \alias{tablature} 5 | \title{Create guitar chord tablature chart.} 6 | \usage{ 7 | tablature(name, desc, include_text = TRUE, include_title = TRUE, 8 | x_labels = NULL, x_axis_label = "String", dot_labels = NULL, 9 | dot_label_size = 2) 10 | } 11 | \arguments{ 12 | \item{name}{The name of the chord} 13 | 14 | \item{desc}{A vector with 6 elements representing strings. 15 | A number indicates the fret and NA indicates a string 16 | should not be played.} 17 | 18 | \item{include_text}{Include tick mark labels on x and y axis. Default is TRUE.} 19 | 20 | \item{include_title}{Include the labels on the x and y axis. Default is TRUE.} 21 | 22 | \item{x_labels}{A vector containing x tick mark labels. Default is string numbers.} 23 | 24 | \item{x_axis_label}{The x axis label. Default is String.} 25 | 26 | \item{dot_labels}{Adds labels in place of dots on frets.} 27 | 28 | \item{dot_label_size}{Set the size of labels used in place of dots on frets.} 29 | } 30 | \description{ 31 | Create guitar chord tablature chart. 32 | } 33 | \examples{ 34 | tablature('G Major', c(3, 2, 0, 0, 0, 3)) 35 | 36 | B_M <- c(NA, 2, 4, 4, 4, 2) 37 | tablature('B Major (bar)', B_M, 38 | x_labels=c(0,1,3,3,3,1), 39 | x_axis_label = 'Finger') 40 | 41 | tablature('B Major (bar)', B_M, 42 | dot_labels = c('','B','F#','B','D#','F#')) 43 | } 44 | 45 | -------------------------------------------------------------------------------- /man/chords.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{chords} 5 | \alias{chords} 6 | \title{A dataset containing chords.} 7 | \format{A data frame chords: 8 | \describe{ 9 | \item{X1}{id field} 10 | \item{note}{note that is the root of the chord} 11 | \item{chord}{name of the chord} 12 | \item{string_1_fret}{Which fret should be pressed on the first string.} 13 | \item{string_2_fret}{Which fret should be pressed on the second string.} 14 | \item{string_3_fret}{Which fret should be pressed on the third string.} 15 | \item{string_4_fret}{Which fret should be pressed on the fourth string.} 16 | \item{string_5_fret}{Which fret should be pressed on the fifth string.} 17 | \item{string_6_fret}{Which fret should be pressed on the sixth string.} 18 | \item{string_1_finger}{Which finger should press the specified fret on the first string.} 19 | \item{string_2_finger}{Which finger should press the specified fret on the second string.} 20 | \item{string_3_finger}{Which finger should press the specified fret on the third string.} 21 | \item{string_4_finger}{Which finger should press the specified fret on the fourth string.} 22 | \item{string_5_finger}{Which finger should press the specified fret on the fifth string.} 23 | \item{string_6_finger}{Which finger should press the specified fret on the sixth string.} 24 | }} 25 | \usage{ 26 | chords 27 | } 28 | \description{ 29 | A dataset containing chords, their location 30 | on a guitar neck, and the standard fingering used 31 | to play them. 32 | } 33 | \keyword{datasets} 34 | 35 | -------------------------------------------------------------------------------- /tests/test_tablature.R: -------------------------------------------------------------------------------- 1 | # chords <- readr::read_csv("data/chords.csv", col_types = readr::cols( 2 | # X1 = readr::col_integer(), 3 | # note = readr::col_character(), 4 | # chord = readr::col_character(), 5 | # string_1_fret = readr::col_integer(), 6 | # string_2_fret = readr::col_integer(), 7 | # string_3_fret = readr::col_integer(), 8 | # string_4_fret = readr::col_integer(), 9 | # string_5_fret = readr::col_integer(), 10 | # string_6_fret = readr::col_integer(), 11 | # string_1_finger = readr::col_integer(), 12 | # string_2_finger = readr::col_integer(), 13 | # string_3_finger = readr::col_integer(), 14 | # string_4_finger = readr::col_integer(), 15 | # string_5_finger = readr::col_integer(), 16 | # string_6_finger = readr::col_integer() 17 | # )) 18 | # 19 | #---- 20 | # save(chords, file='data/chords.RData') 21 | #---- 22 | # library(ggplot2) 23 | # library(dplyr) 24 | # library(tibble) 25 | # library(gridExtra) 26 | # library(readr) 27 | # # TODO Maybe make a vigenette based on the examples ??? 28 | # G_M <- c(3, 2, 0, 0, 0, 3) 29 | # 30 | # B_M <- c(NA, 2, 4, 4, 4, 2) 31 | # C_M <- c(NA, 3, 2, 0, 1, 0) 32 | # C_M <- c(NA, 3, 2, 0, 1, 0) 33 | # C_M_bar <- c(8, 10, 10, 9, 8, 8) 34 | # D_M <- c(NA, NA, 0, 2, 3, 2) 35 | # F_M7 <- c(NA, NA, 3, 2, 1, 0) 36 | # 37 | # e_m <- c(0, 2, 2, 0, 0, 0) 38 | # a_m <- c(NA, 0, 2, 2, 1, 0) 39 | # b_m <- c(NA, 2, 4, 4, 3, 2) 40 | # 41 | # G_Major <- tablature('G Major', G_M) 42 | # C_Major <- tablature('C Major', C_M, TRUE, FALSE) 43 | # D_Major <- tablature('D Major', D_M, FALSE, FALSE) 44 | # e_minor <- tablature('e minor', e_m) 45 | # a_minor <- tablature('a minor', a_m, TRUE, FALSE) 46 | # b_minor <- tablature('b minor', b_m) 47 | # 48 | # B_Major <- tablature('B Major (bar)', B_M, 49 | # x_labels=c(0,1,3,3,3,1), 50 | # x_axis_label = 'Finger' 51 | # ) 52 | # B_Major_notes <- tablature('B Major (bar)', B_M, 53 | # x_labels=c('','B','F#','B','D#','F#'), 54 | # x_axis_label = 'Notes' 55 | # ) 56 | # B_Major_note_labels <- tablature('B Major (bar)', B_M, 57 | # x_labels=c(0,1,3,3,3,1), 58 | # x_axis_label = 'Finger', 59 | # dot_labels = c('','B','F#','B','D#','F#') 60 | # ) 61 | # 62 | # C_Major_bar <- tablature('C Major (bar)', C_M_bar, TRUE, FALSE) 63 | # 64 | # F_Major_7 <- tablature('F Major 7', F_M7, 65 | # x_labels=c(0,0,4,3,2,0), 66 | # x_axis_label = 'Finger' 67 | # ) 68 | # 69 | # e_m_add9 <- c(0,2,4,0,0,0) 70 | # e_minor_add9 <- tablature('e minor add 9', e_m_add9) 71 | # 72 | # grid.arrange(G_Major, C_Major, D_Major, 73 | # a_minor, b_minor, 74 | # B_Major, B_Major_notes, B_Major_note_labels, 75 | # F_Major_7, C_Major_bar, 76 | # e_minor, e_minor_add9, 77 | # ncol = 4) 78 | # 79 | # select_chords('c', 'Major add 9', string_5_fret = 3) %>% 80 | # filter(row_number()==1) %>% 81 | # select(matches('fret')) %>% 82 | # t() %>% as.vector() %>% 83 | # notes_for_frets() 84 | # 85 | # 86 | # G_M_scale <- c(3, 0,0,0,NA,NA, 87 | # NA,2,2,NA,NA,NA, 88 | # NA,3,4,NA,NA,NA) 89 | # 90 | # tablature('G Major Scale', G_M_scale, 91 | # dot_labels=c(2, 0,0,0,NA,NA, 92 | # NA, 1,1,NA,NA,NA, 93 | # NA, 2,3,NA,NA,NA)) 94 | # 95 | # 96 | # # df <- chords %>% filter(chord=='Major') 97 | # # x <- list() 98 | # # by(df, 1:nrow(df), function(row){ 99 | # # desc <- row %>% select(matches('fret')) %>% t() %>% as.vector() 100 | # # x<-c(x, tablature(paste(row$note, row$chord), desc)) 101 | # # }) 102 | # # 103 | # # 104 | # # grid.arrange(x) 105 | # # grid.arrange(x, ncol=3) 106 | # 107 | # tablature('C Major', C_M, TRUE, TRUE) 108 | # tablature('C Major', C_M, TRUE, FALSE) # Remove axis titles 109 | # tablature('C Major', C_M, FALSE, FALSE) # Remove axis labels 110 | # 111 | # 112 | -------------------------------------------------------------------------------- /vignettes/my-vignette.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "GGGuitar" 3 | author: "Casimir Saternos" 4 | date: "`r Sys.Date()`" 5 | output: rmarkdown::html_vignette 6 | vignette: > 7 | %\VignetteIndexEntry{Intro to GGGuitar} 8 | %\VignetteEngine{knitr::rmarkdown} 9 | %\VignetteEncoding{UTF-8} 10 | --- 11 | 12 | This vignettes is a brief introduction to the ggguitar package. The graphics are based on ggplot2 and processing on the tidyverse 13 | in general. 14 | 15 | ```{r} 16 | library(ggguitar) 17 | library(tibble) 18 | library(ggplot2) 19 | 20 | # Ignoring warnings 21 | options( warn = -1 ) 22 | ``` 23 | 24 | Special thanks to Dr. Hadley Wickham and the crew at RStudio whose work does all of the heavy lifting. 25 | 26 | ## Examples of Tablature 27 | 28 | A chord in ggguitar is represented as a vector containing 6 elements. Each element represents a string. A numeric value 29 | represents the fret where a finger is placed. Zero represents an open string, NA represents a string not played (either skipped or muted). 30 | 31 | A G Major chord can be represented using the following vector. 32 | 33 | ```{r} 34 | G_M <- c(3, 2, 0, 0, 0, 3) 35 | ``` 36 | 37 | The ggguitar method can be used to create the tablature for this chord. The numbers in the vector represent fret positions with zeros indicating open strings. By default the x and y axis are labeled as Strings and Frets along with associated numbers. 38 | 39 | ```{r} 40 | ggguitar::tablature('G Major', G_M) 41 | ``` 42 | 43 | If a given string is not to be played, an NA is used rather than an integer representing the fret number. 44 | 45 | ```{r} 46 | B_M <- c(NA, 2, 4, 4, 4, 2) 47 | ggguitar::tablature('B Major', B_M) 48 | ``` 49 | 50 | Both open strings and ignored/muted strings can be included in the same chord. 51 | ```{r} 52 | C_M <- c(NA, 3, 2, 0, 1, 0) 53 | ggguitar::tablature('C Major', C_M) 54 | ``` 55 | 56 | Chords need not be restricted to first position. In the next example, a bar chord further up the neck is represented. 57 | ```{r} 58 | C_M_bar <- c(8, 10, 10, 9, 8, 8) 59 | ggguitar::tablature('C Major (bar)', C_M_bar) 60 | ``` 61 | 62 | ## Combining Tablature Images 63 | Charts can be assigned to variables and then displayed 64 | together using grid.arrange. 65 | ```{r, fig.width=6} 66 | D_M <- c(NA, NA, 0, 2, 3, 2) 67 | F_M7 <- c(NA, NA, 3, 2, 1, 0) 68 | e_m <- c(0, 2, 2, 0, 0, 0) 69 | a_m <- c(NA, 0, 2, 2, 1, 0) 70 | b_m <- c(NA, 2, 4, 4, 3, 2) 71 | 72 | G_Major <- tablature('G Major', G_M) 73 | C_Major <- tablature('C Major', C_M, TRUE, FALSE) 74 | D_Major <- tablature('D Major', D_M, FALSE, FALSE) 75 | e_minor <- tablature('e minor', e_m) 76 | a_minor <- tablature('a minor', a_m, TRUE, FALSE) 77 | b_minor <- tablature('b minor', b_m) 78 | 79 | gridExtra::grid.arrange(G_Major, C_Major, D_Major, 80 | a_minor, b_minor, e_minor, 81 | ncol = 3) 82 | ``` 83 | 84 | ## Labeled Frets 85 | In place of dots on frets, labels can be assigned. These can contain finger numbers, scale degrees or any other characters of interest. 86 | ```{r} 87 | tablature("A7", c(5, NA, 5, 6, 5, NA), dot_labels=c("Root", NA, "7th", "3rd", "5th", NA)) 88 | ``` 89 | 90 | The appearance of the labels varies depending on the size of the rendered image. You can assign a size for these labels explicitly. 91 | 92 | ```{r} 93 | tablature("A7", c(5, NA, 5, 6, 5, NA), dot_labels=c("R", NA, "7", "3", "5", NA), dot_label_size = 5) 94 | ``` 95 | 96 | ## Scales 97 | 98 | Scales can be presented as well. 99 | 100 | ```{r} 101 | G_M_scale <- c(3, 0,0,0,NA,NA, 102 | NA,2,2,NA,NA,NA, 103 | NA,3,4,NA,NA,NA) 104 | 105 | tablature('G Major Scale', 106 | G_M_scale, 107 | dot_labels=c(2, 0,0,0,NA,NA, 108 | NA, 1,1,NA,NA,NA, 109 | NA, 2,3,NA,NA,NA), 110 | dot_label_size = 5) 111 | ``` 112 | 113 | ## Chords for Left-handed Guitars 114 | 115 | The reverse function - called rev() - in Base-R can be used to render a left-handed version of a chord. If you want the strings on the x-axis, these should be passed using the x_labels parameter. 116 | 117 | ```{r} 118 | ggguitar::tablature('G Major (Left-handed)', 119 | rev(G_M), 120 | x_labels = c(1,2,3,4,5,6)) 121 | ``` 122 | 123 | 124 | ```{r} 125 | sessionInfo() 126 | ``` 127 | -------------------------------------------------------------------------------- /R/guitar_chords.R: -------------------------------------------------------------------------------- 1 | # TODO - add a complete list of chords 2 | 3 | #View(chords) 4 | # TODO - Perhaps expand to a database. Also could include 5 | # - Instruments (guitar, tuning) 6 | # - Tuning (standard strings) 7 | # - Chords - based on the above. 8 | # - create data frame of scales. 9 | # - Progressions I-IV-V, ii-V-I, etc 10 | 11 | # TODO - refactor Make sure everything parameterized that should be 12 | # TODO - other music related graphs: 13 | # - Manuscript, Piano keyboard, circle of fifths 14 | # TODO - handle groups faceting 15 | # TODO - warnings - fix or supress? 16 | # options( warn = -1 ) 17 | 18 | # 19 | #'Create guitar chord tablature chart. 20 | #' @export 21 | #' @param name The name of the chord 22 | #' @param desc A vector with 6 elements representing strings. 23 | #' A number indicates the fret and NA indicates a string 24 | #' should not be played. 25 | #' @param include_text Include tick mark labels on x and y axis. Default is TRUE. 26 | #' @param include_title Include the labels on the x and y axis. Default is TRUE. 27 | #' @param x_labels A vector containing x tick mark labels. Default is string numbers. 28 | #' @param x_axis_label The x axis label. Default is String. 29 | #' @param dot_labels Adds labels in place of dots on frets. 30 | #' @param dot_label_size Set the size of labels used in place of dots on frets. 31 | #' 32 | #' @examples 33 | #' tablature('G Major', c(3, 2, 0, 0, 0, 3)) 34 | #' 35 | #' B_M <- c(NA, 2, 4, 4, 4, 2) 36 | #' tablature('B Major (bar)', B_M, 37 | #' x_labels=c(0,1,3,3,3,1), 38 | #' x_axis_label = 'Finger') 39 | #' 40 | #' tablature('B Major (bar)', B_M, 41 | #' dot_labels = c('','B','F#','B','D#','F#')) 42 | # 43 | tablature <- 44 | function(name, 45 | desc, 46 | include_text = TRUE, 47 | include_title = TRUE, 48 | x_labels=NULL, 49 | x_axis_label = 'String', 50 | dot_labels = NULL, 51 | dot_label_size = 2 52 | ) { 53 | 54 | # The declaration of Fret is just used to overcome a 55 | # CRAN check issue... 56 | # tablature: no visible binding for global variable 'Fret' 57 | # Undefined global functions or variables: 58 | # Fret 59 | Fret <- NULL 60 | 61 | # 6 strings, but we need to use rep to represent scales... mutliple 62 | # notes per string 63 | strings <- rep(seq(6,1,by=-1), length.out = length(desc)) 64 | frets <- c(4, 3, 2, 1, 0) 65 | open_strings <- rep(0, length(desc)) 66 | not_played_x <- (6:1)[which(is.na(desc))] 67 | not_played_y <- rep(0, length(not_played_x)) 68 | 69 | if (is.null(x_labels)){ 70 | x_labels <- strings 71 | } 72 | 73 | # Slide up the neck if needed. 74 | min_y <- 0 75 | if (min(desc, na.rm=TRUE) > 3) { 76 | min_y <- min(desc, na.rm=TRUE) - 1 77 | frets <- frets + min_y 78 | } 79 | 80 | desc <- as.numeric(sub(-0.5, 0, (desc - 0.5))) # Position finger before the fret. 81 | fret_positions <- tibble::tibble(strings, Fret = desc) 82 | 83 | p <- ggplot2::ggplot(fret_positions, 84 | ggplot2::aes(x = strings, 85 | y = Fret)) + ggplot2::geom_point() 86 | 87 | if (!is.null(dot_labels)){ 88 | p <- ggplot2::ggplot(fret_positions,ggplot2::aes(x=strings, 89 | y=Fret, 90 | label=c(dot_labels))) + 91 | ggplot2::geom_label(size = dot_label_size) 92 | } 93 | 94 | # Mark open strings 95 | p <- p + 96 | ggplot2::geom_point(ggplot2::aes(x = strings, 97 | y = open_strings), 98 | colour = 'white', alpha = 0.5) + 99 | ggplot2::theme(panel.grid.minor = ggplot2::element_blank()) + 100 | ggplot2::coord_fixed(ratio = 1.2) 101 | 102 | # Add X for not played / muted strings 103 | # p <- p + geom_point(ggplot2::aes(x=not_played_x, 104 | # y=not_played_y, 105 | # shape=4, size=10)) + 106 | # scale_shape_identity() 107 | 108 | p <- p + 109 | ggplot2::scale_y_reverse(breaks = frets, 110 | labels = frets, 111 | limits = c(max(frets), min_y)) + 112 | ggplot2::scale_x_reverse(breaks = strings, 113 | labels = x_labels) + 114 | ggplot2::ggtitle(name) 115 | 116 | if (!include_text) { 117 | p <- p + ggplot2::theme(axis.text = ggplot2::element_blank(), axis.ticks = ggplot2::element_blank()) 118 | } 119 | 120 | if (include_title) { 121 | p <- p + ggplot2::xlab(x_axis_label) 122 | }else{ 123 | p <- p + ggplot2::theme(axis.title = ggplot2::element_blank()) 124 | } 125 | 126 | p + ggplot2::theme(legend.position="none") 127 | } 128 | 129 | 130 | #' Chord for Frets 131 | #' 132 | #' Return the notes for a given set of frets for a specified tuning. 133 | #' Preserves NAs indicating muted strings. 134 | #' @export 135 | #' @param frets A 6 element vector representing fret positions. 136 | #' @param tuning A 6 element vector representing notes of open strings. 137 | #' 138 | #' @return Returns a 6 element vector of note names. 139 | #' 140 | #' @examples chord_for_frets(c(NA, 3, 2, 0, 1, 0)) 141 | #' 142 | #' @seealso \code{\link{notes_for_frets}} 143 | #' 144 | chord_for_frets <- function(frets, 145 | tuning=c('e','a','d','g','b','e')){ 146 | notes<-rep(c('a','a#','b','c','c#','d','d#','e','f','f#','g','g#'),4) 147 | chord=c() 148 | for (i in 1:6){ 149 | chord[i] <- notes[match(tuning[i], notes) + frets[i]] 150 | } 151 | chord 152 | } 153 | 154 | # 155 | #' This function is similar to \code{\link{chord_for_frets}} but 156 | #' also handles scales. 157 | #' Unlike chords_for_frets, this function removes NAs. 158 | #' This means there are no muted strings identified 159 | #' if a chord is passed in the frets argument. 160 | #' 161 | #' @export 162 | #' @param frets A vector representing fret positions. 163 | #' @param tuning A 6 element vector representing notes of open strings. 164 | #' @return Returns a vector of note names. 165 | #' @examples G_M_scale <- c(3, 0, 0, 0, NA, NA, 166 | #' NA, 2, 2, NA, NA, NA, 167 | #' NA, 3, 4, NA, NA, NA) 168 | #' notes_for_frets(G_M_scale) 169 | #' 170 | #' @seealso \code{\link{chord_for_frets}} 171 | 172 | notes_for_frets <- function(frets, 173 | tuning=c('e','a','d','g','b','e')){ 174 | notes<-rep(c('a','a#','b','c','c#','d','d#','e','f','f#','g','g#'),4) 175 | 176 | m <- matrix(frets, nrow=6) 177 | idx <- 0 178 | return_notes=rep(NA, length(frets)) 179 | 180 | for (str in 1:nrow(m)){ 181 | for (i in 1:ncol(m)){ 182 | idx <- idx + 1 183 | offset <- m[str,i] 184 | if (length(offset) == 0){ 185 | offset <- 0 186 | } 187 | return_notes[idx] <- notes[match(tuning[str], notes) + offset] 188 | } 189 | } 190 | 191 | return_notes[!is.na(return_notes)] 192 | 193 | } 194 | 195 | #' Narrow (Filter) Chord Selection 196 | #' 197 | #' This function filters rows in the chord data frame 198 | #' by criteria passed in and accounts for nulls. 199 | #' The nifty bit is - given a full set of chords, you can get chords that 200 | #' use a given fret or frets. 201 | #' @param chords A data frame of chords. 202 | #' @param value The value to be filtered. 203 | #' @param name The name to be filtered. 204 | #' @return Returns a data frame of chords. 205 | narrow_chord <- function(chords, value, name){ 206 | if (!is.null(value) && value !=''){ 207 | filter_expr <- paste(name, '==', value) 208 | chords <- dplyr::filter_(chords, filter_expr) 209 | } 210 | chords 211 | } 212 | 213 | #' Select chords by criteria 214 | #' 215 | #' @export 216 | #' @param note_name Root of the chord. 217 | #' @param chord_name Name of the chord. 218 | #' @param string_1_fret Fret location on the 1st string. 219 | #' @param string_2_fret Fret location on the 2nd string. 220 | #' @param string_3_fret Fret location on the 3rd string. 221 | #' @param string_4_fret Fret location on the 4th string. 222 | #' @param string_5_fret Fret location on the 5th string. 223 | #' @param string_6_fret Fret location on the 6th string. 224 | #' @return Returns a data frame of chords. 225 | #' @examples 226 | #' select_chords(chord_name = 'Major', string_5_fret = 3) 227 | #' select_chords(note='d') 228 | select_chords <- function( 229 | note_name = NULL, 230 | chord_name = NULL, 231 | string_1_fret = NULL, 232 | string_2_fret = NULL, 233 | string_3_fret = NULL, 234 | string_4_fret = NULL, 235 | string_5_fret = NULL, 236 | string_6_fret = NULL 237 | ){ 238 | 239 | chord <- ggguitar::chords 240 | chord <- narrow_chord(chord, shQuote(chord_name), 'chord') 241 | chord <- narrow_chord(chord, shQuote(note_name), 'note') 242 | chord <- narrow_chord(chord, string_1_fret, 'string_1_fret') 243 | chord <- narrow_chord(chord, string_2_fret, 'string_2_fret') 244 | chord <- narrow_chord(chord, string_3_fret, 'string_3_fret') 245 | chord <- narrow_chord(chord, string_4_fret, 'string_4_fret') 246 | chord <- narrow_chord(chord, string_5_fret, 'string_5_fret') 247 | chord <- narrow_chord(chord, string_6_fret, 'string_6_fret') 248 | 249 | chord 250 | } 251 | --------------------------------------------------------------------------------