% -------------------------------------------------------------------------- % the GUITARCHORDSCHEMES package % % Guitar Chord and Scale Tablatures with TikZ % % -------------------------------------------------------------------------- % Clemens Niederberger % Web: https://bitbucket.org/cgnieder/guitarchordschemes/ % E-Mail: contact@mychemistry.eu % -------------------------------------------------------------------------- % Copyright 2013-2016 Clemens Niederberger % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3 % of this license or (at your option) any later version. % The latest version of this license is in % http://www.latex-project.org/lppl.txt % and version 1.3 or later is part of all distributions of LaTeX % version 2005/12/01 or later. % % This work has the LPPL maintenance status `maintained'. % % The Current Maintainer of this work is Clemens Niederberger. % -------------------------------------------------------------------------- % The guitarchordschemes package consists of the files % - guitarchordschemes.sty, % - guitarchordschemes_en.tex, % - guitarchordschemes_en.pdf, % - README % -------------------------------------------------------------------------- % If you have any ideas, questions, suggestions or bugs to report, please % feel free to contact me. % -------------------------------------------------------------------------- % % package info and requirements: \NeedsTeXFormat{LaTeX2e} \def\gcs@date{2016/08/16} \def\gcs@version{v0.7} \def\gcs@description{Guitar Chord and Scale Tablatures with TikZ (CN)} \ProvidesPackage{guitarchordschemes}[\gcs@date\space \gcs@version\space \gcs@description] \RequirePackage{tikz,cnltx-base} \usetikzlibrary{shapes.misc,arrows,calc} % -------------------------------------------------------------------------- % message handling \newcommand*\gcs@error@message{% For details have a look at the `guitarchordschemes' manual.% } \cnltx@create@generic@message{gcs}{guitarchordschemes}{Error}{\gcs@error@message} \cnltx@create@generic@message{gcs}{guitarchordschemes}{Warning}{} \cnltx@create@generic@message{gcs}{guitarchordschemes}{WarningNoLine}{} \cnltx@create@generic@message{gcs}{guitarchordschemes}{Info}{} \newcommand*\gcs@missing@date@error[2]{% \gcs@error {#1: empty #2} {#1: It seems you didn't specify the #2}% } \newrobustcmd*\gcs@def[1]{% \ifdef{#1} {% \gcs@error {The macro \string#1\space is already defined} {% The macro \string#1\space is already defined. Please let the package author know% }% } {\protected\def#1}% } \newrobustcmd*\gcs@deprecated@option[2]{% \gcs@warning{Since version #1 the option `#2' has been dropped}% } % -------------------------------------------------------------------------- % package options and setup: \newcommand*\gcs@finger@font{\sffamily\small} \newcommand*\gcs@position@font{\sffamily} \newcommand*\gcs@name@font{\large} \newcommand*\gcs@string@name@format{\sffamily\small} \newcommand*\gcs@name@distance{.5em} \newcommand*\gcs@x@unit{.8cm} \newcommand*\gcs@y@unit{.8cm} \newcommand*\gcs@line@width{1pt} \newcommand*\gcs@finger@radius{.1875} \newcommand*\gcs@finger@x@offset{.375} \newcommand*\gcs@finger@y@offset{.275} \newcommand*\gcs@angle{0} \newcommand*\gcs@string@number{6} \newcommand*\gcs@setstringnumber[1]{% \ifnumless{#1}{1} {% \gcs@warning{You can't use less than one string. Setting string number to 1}% \def\gcs@string@number{1}% } {% \ifnumgreater{#1}{7} {% \gcs@warning{You can't use more than seven strings. Setting string number to 6}% \def\gcs@string@number{6}% } {\def\gcs@string@number{#1}}% }% } \newbool{gcs@switch@name} \newcommand*\gcs@chordscheme@fret@number{4} \newcommand*\gcs@scales@fret@number{6} \newrobustcmd*\gcs@chord@tuning[1]{% \foreach \string@name [count=\x] in {#1} {\csxdef{guitar@string@\x}{\expandonce\string@name}}% } \newbool{gcs@restrict@boundingbox} \newcommand*\gcs@restrictboundingbox[1]{ \ifbool{gcs@restrict@boundingbox} { \ifnumequal{\gcs@string@number}{1} {\useasboundingbox (0,-.4) --++ (1.5*\csname gcs@#1@fret@number\endcsname,.8) ; } { \useasboundingbox (bass) rectangle (1.5*\csname gcs@#1@fret@number\endcsname,{.8*(\gcs@string@number-1)}) ; } }{} } \pgfkeys{ guitarchordschemes/.cd , x-unit/.code = \def\gcs@x@unit{#1} , y-unit/.code = \def\gcs@y@unit{#1} , rotate/.code = \def\gcs@angle{#1} , strings/.code = \gcs@setstringnumber{#1} , finger-format/.code = \def\gcs@finger@font{#1} , finger-format+/.code = \expandafter\def\expandafter\gcs@finger@font \expandafter{\gcs@finger@font#1} , position-format/.code = \def\gcs@position@font{#1} , position-format+/.code = \expandafter\def\expandafter\gcs@position@font \expandafter{\gcs@position@font#1} , name-format/.code = \def\gcs@name@font{#1} , name-format+/.code = \expandafter\def\expandafter\gcs@name@font \expandafter{\gcs@name@font#1} , name-distance/.code = \def\gcs@name@distance{#1} , name-below/.is if = gcs@switch@name , chord-name-cs/.code = {\let\gcs@chord@name@command=#1} , scales-name-cs/.code = {\let\gcs@scales@name@command=#1} , string-name-format/.code = \def\gcs@string@name@format{#1} , string-name-format+/.code = \expandafter\def\expandafter\gcs@string@name@format \expandafter{\gcs@string@name@format#1} , chord-frets/.code = \ifnumless{#1}{4} {% \gcs@warning{You cannot use less than 4 frets for a chord!}% \def\gcs@chordscheme@fret@number{4}% } {\def\gcs@chordscheme@fret@number{#1}} , scales-frets/.code = \ifnumless{#1}{6} {% \gcs@warning{You cannot use less than 6 frets for a scale!}% \def\gcs@scales@fret@number{6}% } {\def\gcs@scales@fret@number{#1}} , line-width/.code = \def\gcs@line@width{#1} , finger-radius/.code = \def\gcs@finger@radius{#1} , finger-x-offset/.code = \def\gcs@finger@x@offset{#1} , finger-y-offset/.code = \def\gcs@finger@y@offset{#1} , finger-style/.code = \tikzset{finger style/.style={#1}} , root-style/.code = \tikzset{root style/.style={#1}} , show-root-style/.code = \tikzset{show root style/.style={#1}} , , ringing-style/.code = \tikzset{ringing style/.style={#1}} , muted-style/.code = \tikzset{muted style/.style={#1}} , tuning/.code = \gcs@chord@tuning{#1} , use-rbc/.code = \gcs@deprecated@option{0.5}{use-rbc} , restrict-bounding-box/.is if = gcs@restrict@boundingbox } % the setup command: \newrobustcmd*\setchordscheme[1]{\pgfqkeys{/guitarchordschemes}{#1}} % some defaults -- need to be set before options are processed: \setchordscheme{ tuning = {E,B,G,D,A,E} , muted-style = {cross out,draw} , root-style = {fill} , show-root-style = {draw} , ringing-style = {draw} , finger-style = {fill} } \ProcessPgfOptions* % -------------------------------------------------------------------------- % settings for the whole scheme: \tikzset{ gcs/finger/.style = { xshift = \gcs@finger@x@offset*\gcs@x@unit , yshift = \gcs@finger@y@offset*\gcs@y@unit , font = \gcs@finger@font } } % setting a chord scheme: \pgfkeys{ gcs/chord/.cd , name/.code = \gdef\gcs@chord@name{#1} , position/.code = \def\gcs@chord@position{#1} , finger/.code = \gcs@chord@finger{#1} , root/.code = \gcs@chord@root{#1} , show-root/.code = \gcs@chord@show@root{#1} , mute/.code = \gcs@chord@mute{#1} , ring/.code = \gcs@chord@ring{#1} , barre/.code = \gcs@chord@barre{#1} , fret-number/.code = \ifnumless{#1}{4} {% \gcs@warning{You cannot use less than 4 frets for a chord!}% \def\gcs@chordscheme@fret@number{4}% } {\def\gcs@chordscheme@fret@number{#1}} } \newrobustcmd*\setfingering[3]{% \pgfkeys{ gcs/scales/.cd , fingering/#1/.code = \gcs@scales@finger{#2} \ifblank{#3}{}{\gcs@scales@root{#3}} , fingering*/#1/.code = \def\gcs@tmp{}% \foreach \gcs@str in {#2,#3} { \xappto\gcs@tmp{\gcs@str,} }% \edef\gcs@tmp{\expandafter\cs@remove@comma\gcs@tmp\q@stop}% \expandafter\gcs@scales@finger\expandafter{\gcs@tmp} , fingering?/#1/.code = \def\gcs@tmp{}% \foreach \gcs@str in {#2,#3} { \xappto\gcs@tmp{\expandafter\cs@remove@finger\gcs@str::\q@stop,} }% \edef\gcs@tmp{\expandafter\cs@remove@comma\gcs@tmp\q@stop}% \expandafter\gcs@scales@finger\expandafter{\gcs@tmp}% }% } \def\cs@remove@finger#1:#2:#3\q@stop{#1} \def\cs@remove@comma#1,\q@stop{#1} % setting a scale: \pgfkeys{ gcs/scales/.cd , name/.code = \gdef\gcs@scales@name{#1} , position/.code = \def\gcs@scales@position{#1} , finger/.code = \gcs@scales@finger{#1} , root/.code = \gcs@scales@root{#1} , fret-number/.code = \ifnumless{#1}{6} {% \gcs@warning{You cannot use less than 6 frets for a scale!}% \def\gcs@scales@fret@number{6}% } {\def\gcs@scales@fret@number{#1}} , fingering/.is choice , fingering*/.is choice , fingering?/.is choice } \setfingering{type 1}{ 1/1:1s, 3/1:2, 5/1:4, 3/2:2, 5/2:4, 2/3:1, 4/3:3, 2/4:1, 3/4:2, 5/4:4, 2/5:1, 5/5:4, 1/6:1s, 3/6:2, 5/6:4 }{5/3:4, 3/5:2} \setfingering{type 1A}{ 3/1:2, 5/1:4, 3/2:2, 5/2:4, 2/3:1, 3/3:2, 5/3:4, 2/4:1, 5/4:4, 1/5:1s, 3/5:2, 5/5:4, 3/6:2, 5/6:4 }{1/1:1s, 3/4:2, 1/6:1s} \setfingering{type 2}{ 2/1:1, 5/1:4, 3/2:2, 5/2:4, 2/3:1, 4/3:3, 5/3:4, 2/4:1, 4/4:3, 2/5:1, 3/5:2, 5/5:4, 2/6:1, 5/6:4 }{3/1:2, 5/4:4, 3/6:2} \setfingering{type 3}{ 2/1:1, 3/1:2, 5/1:4, 2/2:1, 5/2:4, 2/3:1, 4/3:3, 2/4:1, 4/4:3, 5/4:4, 2/5:1, 4/5:3, 2/6:1, 3/6:2, 5/6:4 }{3/2:2, 5/5:4} \setfingering{type 4}{ 2/1:1, 4/1:3, 2/2:1, 3/2:2, 5/2:4, 4/3:3, 2/4:1, 4/4:3, 6/4:4s, 2/5:1, 4/5:3, 5/5:4, 2/6:1, 4/6:3 }{5/1:4, 2/3:1, 5/6:4} % -------------------------------------------------------------------------- % the internal commands % placing fingers: % /: \newrobustcmd*\gcs@chord@finger[1]{% \foreach \gcs@finger@spec in {#1} { \expandafter\gcs@get@finger@data\gcs@finger@spec::\q@stop \ifdefvoid\gcs@finger@x {\gcs@missing@date@error{finger}{position}} { \pgfmathsetmacro\gcs@finger@fret{1.5*\gcs@finger@x-0.75} \ifdefvoid\gcs@finger@y {\gcs@missing@date@error{finger}{string}} { \pgfmathsetmacro\gcs@finger@string{(\gcs@string@number-\gcs@finger@y)*4/5} \draw[finger style] (\gcs@finger@fret,\gcs@finger@string) circle (\gcs@finger@radius*\gcs@x@unit) ; \node[gcs/finger] at (\gcs@finger@fret,\gcs@finger@string) {\gcs@finger@number} ; } } } } \let\gcs@scales@finger\gcs@chord@finger \gcs@def\gcs@get@finger@data#1/#2:#3:#4\q@stop{% \def\gcs@finger@x{#1}% \def\gcs@finger@y{#2}% \def\gcs@finger@number{#3}% } % placing a barre: % /-: \newrobustcmd*\gcs@chord@barre[1]{% \foreach \gcs@barre@spec in {#1} { \expandafter\gcs@get@barre@data\gcs@barre@spec::\q@stop \ifdefvoid\gcs@barre@x {\gcs@missing@date@error{barre}{position}} {\pgfmathsetmacro\gcs@barre@fret{1.5*\gcs@barre@x-0.75}} \ifdefvoid\gcs@barre@fromto {\gcs@missing@date@error{barre}{string range}} { \expandafter\gcs@barre@getstrings\gcs@barre@fromto--\q@stop \pgfmathsetmacro\gcs@barre@lower@string{(\gcs@string@number-\gcs@barre@lower@y)*4/5} \pgfmathsetmacro\gcs@barre@upper@string{(\gcs@string@number-\gcs@barre@upper@y)*4/5} \draw[finger style,round cap-round cap,line width=2*\gcs@finger@radius*\gcs@x@unit] (\gcs@barre@fret,\gcs@barre@lower@string) node[gcs/finger] {\gcs@barre@finger} ++ (0,\gcs@finger@radius*\gcs@x@unit) -- ($(\gcs@barre@fret,\gcs@barre@upper@string)+(0,-\gcs@finger@radius*\gcs@x@unit)$) ; } } } \gcs@def\gcs@get@barre@data#1/#2:#3:#4\q@stop{% \def\gcs@barre@x{#1}% \def\gcs@barre@fromto{#2}% \def\gcs@barre@finger{#3}% } \gcs@def\gcs@barre@getstrings#1-#2-#3\q@stop{% \ifx#3-\relax \def\gcs@barre@lower@y{#1}% \def\gcs@barre@upper@y{#2}% \else \gcs@error {barre: wrong string range syntax} {barre: wrong string range syntax}% \fi } % placing root fingers: % /: \newrobustcmd*\gcs@chord@root[1]{% \foreach \gcs@finger@spec in {#1} { \expandafter\gcs@get@finger@data\gcs@finger@spec::\q@stop \ifdefvoid\gcs@finger@x {\gcs@missing@date@error{root}{position}} { \pgfmathsetmacro\gcs@finger@fret{1.5*\gcs@finger@x-0.75} \ifdefvoid\gcs@finger@y {\gcs@missing@date@error{root}{string}} { \pgfmathsetmacro\gcs@finger@string{(\gcs@string@number-\gcs@finger@y)*4/5} \node[minimum size=2*\gcs@finger@radius*\gcs@x@unit,inner sep=0pt,root style] at (\gcs@finger@fret,\gcs@finger@string) {} ; \node[gcs/finger] at (\gcs@finger@fret,\gcs@finger@string) {\gcs@finger@number} ; } } } } \let\gcs@scales@root\gcs@chord@root % placing ghost roots: % / \newrobustcmd*\gcs@chord@show@root[1]{% \foreach \gcs@finger@spec in {#1} { \expandafter\gcs@get@finger@data\gcs@finger@spec::\q@stop \ifdefvoid\gcs@finger@x {\gcs@missing@date@error{show-root}{position}} { \pgfmathsetmacro\gcs@finger@fret{1.5*\gcs@finger@x-0.75} \ifdefvoid\gcs@finger@x {\gcs@missing@date@error{show-root}{string}} { \pgfmathsetmacro\gcs@finger@string{(\gcs@string@number-\gcs@finger@y)*4/5} \node[ minimum size=2*\gcs@finger@radius*\gcs@x@unit, inner sep=0pt, show root style] at (\gcs@finger@fret,\gcs@finger@string) {} ; } } } } % muted strings: \newrobustcmd*\gcs@chord@mute[1]{% \foreach \muted@string in {#1} { \pgfmathsetmacro\muted@string@pos{(6-\muted@string)*4/5} \node[muted style] at (0,\muted@string@pos) {} ; } } % ringing strings: \newrobustcmd*\gcs@chord@ring[1]{% \foreach \ringing@string in {#1} { \pgfmathsetmacro\ringing@string@pos{(\gcs@string@number-\ringing@string)*4/5} \draw[ringing style] (0,\ringing@string@pos) circle (\gcs@finger@radius*\gcs@x@unit) ; } } % the chord name: \newrobustcmd*\gcs@place@chord@name[1]{% \node[ label={[text height=1.5ex,text depth=.2ex,font=\gcs@name@font, label distance=\gcs@name@distance]\ifbool{gcs@switch@name}{below}{above}:{% \foreach \gcs@chord@name@variant in {#1} {% % \space \expandafter\gcs@chord@name@command \expandafter{\gcs@chord@name@variant}% % \space }% }}] at (diagram.\ifbool{gcs@switch@name}{south}{north}) {} ; } \newrobustcmd*\gcs@chord@name@command[1]{#1} % the scale name: \newrobustcmd*\gcs@place@scales@name[1]{% \node[ label={[text height=1.5ex,text depth=.2ex,font=\gcs@name@font, label distance=\gcs@name@distance]\ifbool{gcs@switch@name}{below}{above}:{% \foreach \gcs@scales@name@variant in {#1} {% % \space \expandafter\gcs@scales@name@command \expandafter{\gcs@scales@name@variant}% % \space }% }}] at (diagram.\ifbool{gcs@switch@name}{south}{north}) {} ; } \newrobustcmd*\gcs@scales@name@command[1]{#1} % -------------------------------------------------------------------------- % the chord scheme command: \newrobustcmd*\gcs@chordscheme[1]{% \begingroup \begin{tikzpicture}[ x=\gcs@x@unit, y=\gcs@y@unit, line width=\gcs@line@width, baseline=(bass) ] \begin{scope}[rotate=\gcs@angle,local bounding box=diagram] \coordinate (bass) at (0,0) ; \gcs@restrictboundingbox{chordscheme} \pgfqkeys{/gcs/chord}{#1}% \foreach \fretnumber in {0,...,\gcs@chordscheme@fret@number} { \ifnumequal{\gcs@string@number}{1} { \draw (1.5*\fretnumber,-.4) --++ (0,.8) ; } { \draw (1.5*\fretnumber,0) -- ++(0,{.8*(\gcs@string@number-1)}) ; } } \foreach \gcs@string in {1,...,\gcs@string@number} { \draw (0,{.8*(\gcs@string@number-\gcs@string)}) node[transform shape, label={[text height=1.5ex,text depth=.2ex]left:% \gcs@string@name@format\csuse{guitar@string@\gcs@string}}] {} --++(1.5*\gcs@chordscheme@fret@number,0) ; } \ifdefvoid\gcs@chord@position {} { \draw (.75,{.8*(\gcs@string@number-1)}) node[transform shape, label={[text height=1.5ex,text depth=.2ex,font=\gcs@position@font]% above:\gcs@chord@position}] {} ; } \end{scope} \ifdefvoid\gcs@chord@name {} {\expandafter\gcs@place@chord@name\expandafter{\gcs@chord@name}} \gdef\gcs@chord@name{} \end{tikzpicture} \endgroup } % -------------------------------------------------------------------------- % the scales command: \newrobustcmd*\gcs@scales[1]{% \begingroup \begin{tikzpicture}[ x=\gcs@x@unit, y=\gcs@y@unit, line width=\gcs@line@width, baseline=(bass) ] \begin{scope}[rotate=\gcs@angle,local bounding box=diagram] \coordinate (bass) at (0,0) ; \gcs@restrictboundingbox{scales} \pgfqkeys{/gcs/scales}{#1}% \foreach \fret in { 0,1,...,\gcs@scales@fret@number } { \draw (1.5*\fret,0) -- (1.5*\fret,{.8*(\gcs@string@number-1)}) ; } \foreach \gcs@string in {1,...,\gcs@string@number} { \draw (0,{.8*(\gcs@string@number-\gcs@string)}) node[transform shape, label={[text height=1.5ex,text depth=.2ex]% left:\gcs@string@name@format\csuse{guitar@string@\gcs@string}}] {} --++(1.5*\gcs@scales@fret@number,0) ; } \ifdefvoid\gcs@scales@position {} { \draw (.75,{.8*(\gcs@string@number-1)}) node[transform shape, label={[text height=1.5ex,text depth=.2ex,font=\gcs@position@font]% above:\gcs@scales@position}] {} ; } \end{scope} \ifdefvoid\gcs@scales@name {} {\expandafter\gcs@place@scales@name\expandafter{\gcs@scales@name}} \gdef\gcs@scales@name{} \end{tikzpicture} \endgroup } % -------------------------------------------------------------------------- % the user commands: \newrobustcmd*\chordscheme[1][]{\gcs@chordscheme{#1}} \newrobustcmd*\scales[1][]{\gcs@scales{#1}} % -------------------------------------------------------------------------- % the symbols for use outside of a scheme: \newrobustcmd*\gcs@fingersymbol{% \tikz\draw[finger style] (0,0) circle (\gcs@finger@radius*\gcs@x@unit);} \newrobustcmd*\rootsymbol{% \tikz\node[root style,minimum size=2*\gcs@finger@radius*\gcs@x@unit] at (0,0) {} ;} \newrobustcmd*\showrootsymbol{% \tikz\node[ show root style, minimum size=2*\gcs@finger@radius*\gcs@x@unit, line width=\gcs@line@width] at (0,0) {} ;} \newrobustcmd*\ringingstring{% \tikz\draw[ ringing style, line width=\gcs@line@width] (0,0) circle (\gcs@finger@radius*\gcs@x@unit);} \newrobustcmd*\mutedstring{% \tikz\node[ muted style, line width=\gcs@line@width] at (0,0) {};} \endinput % -------------------------------------------------------------------------- % HISTORY 2013/04/28 v0.1 - first version 2013/04/29 v0.1a - added error handling and messages 2013/04/30 v0.2 - it's stupid to set colors explicitly -- better define TikZ styles for this 2013/05/01 v0.3 - added \scales command 2013/05/01 v0.3a - set all lengths as multiples of the base unit 2013/08/25 v0.4 - added scale option that allows variable number of frets 2014/07/16 v0.5 - add `inner sep=0pt' to `root' and `show root' styles 2014/09/15 v0.6 - new options `chord-frets', `scales-frets' and `fret-number' 2016/08/16 v0.7 - new option `strings=' makes the string number adaptable which allows creation of ukulele and bass guitar diagrams - new option `name-below' - new option `rotate=' - new option `name-distance' - new command \newfingering{name}{fingers}{roots}