% % Copyright 2018 Steven Franzen % % This file is part of chordbox. % % Chordbox 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. % % Chordbox has the LPPL maintenance status `maintained'. % % The Current Maintainer of chordbox is Steven Franzen. % \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{chordbox}[2019/04/14 v1.0 Minor improvement to documentation] \RequirePackage{tikz, xifthen, xstring} \usetikzlibrary{shapes.misc, scopes, backgrounds} \newif\ifcb@startbarre % Set up keys for the drawing code \pgfqkeys{/chordbox}{ % This fills a bar of width 0.4 that scales properly, without requiring % extra libraries draw barre/.code 2 args={% \fill (#1) -- +(0, -0.2) -| (#2) -- +(0, 0.2) -| cycle; }, draw barre/.value required, % Number of frets displayed numfrets/.initial=4, % Base fret number parser base fret/.code={fr\raisebox{.5ex}{\scriptsize#1}}, % Chord name parser name/.code=\ensuremath{\mathrm{#1}}, name/.value required, % Configuration of text below the chord box and on the nodes text below/.is choice, text below/none/.code={\def\cb@textbelow{0}}, text below/fingering/.code={\def\cb@textbelow{1}}, text below/pitch/.code={\def\cb@textbelow{2}}, text below/fingering, text on node/.is choice, text on node/none/.code={\def\cb@textonnode{0}}, text on node/fingering/.code={\def\cb@textonnode{1}}, text on node/pitch/.code={\def\cb@textonnode{2}}, text on node/none, % Symbols for pitch notation flat symbol/.initial=\flat, sharp symbol/.initial=\sharp, % Pitch name settings; arrays only seem to work with TeX macros pitch names/.store in=\cb@pitchnames, pitch names={"A","A\#","B","C","C\#","D","D\#","E","F","F\#","G","G\#"}, tuning/.store in=\cb@tuning, tuning={"E","A","D","G","B","E"}, % The base fret of a given chord box @basefret/.initial=1, % Calculate the given fret position #1, corrected for the base fret @fretnum/.code=\pgfmathtruncatemacro{\fretnum}{% 1 + #1 - \pgfkeysvalueof{/chordbox/@basefret} }, % Whether the barre has yet to be started @start barre/.is if=cb@startbarre, % Find and typeset pitch of string number #1 at fret number #2 @typeset pitch/.code 2 args={ \pgfmathparse{{\cb@tuning}[#1-1]} \ifnum#2=0 \pgfkeys{@replace symbols=\pgfmathresult} \else \foreach \p in {0,...,11} {% \pgfmathsetmacro{\stringpitch}{{\cb@pitchnames}[\p]}% \if\stringpitch\pgfmathresult \pgfmathparse{{\cb@pitchnames}[mod(\p + #2, 12)]} \pgfkeys{@replace symbols=\pgfmathresult}% \breakforeach \fi } \fi }, % Replace pitch text with math symbols @replace symbols/.code={% \def\#{\ensuremath{\pgfkeysvalueof{/chordbox/sharp symbol}}}% \StrSubstitute{#1}{b}{% \ensuremath{\pgfkeysvalueof{/chordbox/flat symbol}}% } } } % Define tikz drawing styles. The muted string symbol size is slightly smaller % to make it visually similar to the open symbol. Both are also placed above % their given coordinate for better separation from the box. \tikzset{ chordbox/.style={baseline, scale=0.25}, chordbox/.value forbidden, fret node text/.style={font=\Large\bfseries,text=white}, fret node text/.value forbidden, pitch text below/.style={font=\tiny}, string/.is choice, string/base/.style={% circle, draw, inner sep=0, minimum size=20, transform shape% }, string/fretted/.style={string/base, fill}, string/open/.style={string/base, above}, string/muted/.style={string/open, cross out, minimum size=19} } % Environment with parts common to both commands \newenvironment{chordboxenv}[3]{% \pgfqkeys{/chordbox}{@basefret={#1}, numfrets/.get=\numfrets} \pgfqkeys{}{.search also=/chordbox} % The code that draws the chord box. Argument #1 specifies the base fret % (>1) of the chord box, #2 is the chord name and #3 the comma-separated % list of finger positions, e.g. {x,0,2:2,2:3,1:1,0}. \begin{tikzpicture}[chordbox]% % Put coordinates at finger positions and above the frets (index 0), % store string count, then draw the string grid and decorations \foreach[count=\n] \fretposition in {#3} { \foreach \fret in {0,...,\numfrets} \coordinate (\n\fret) at (\n - 1, 0.5 - \fret); % Extra coordinate for text below each string \coordinate (\n) at (\n - 1, -\numfrets); } \draw grid (\n - 1, -\numfrets); \ifthenelse{\isempty{#1}\or#1<2}{% Draw the "nut" \fill rectangle (\n - 1, .2); }{% Draw the position indicator \node[left] at (11) {\pgfkeys{base fret={#1}}}; } % Center chord name over strings \pgfmathparse{0.5 * (\n - 1)} \node[above] at (\pgfmathresult, 1.25) {\pgfkeys{name={#2}}}; % Draw the string symbols according to argument #3 \foreach[count=\s] \fret in {#3} { \ifnum\pdfmatch{^[0-9]+}{\fret}=1 \StrBehind{\pdflastmatch 0}{>}[\num] \StrBehind{\fret}{:}[\frettext] \def\pitch{\pgfkeys{@typeset pitch={\s}{\num}}} \let\nodetext\empty \ifcase\cb@textonnode \or \let\nodetext\frettext % 1 \or \let\nodetext\pitch % 2 \fi \ifnum\num=0 \node[string=open, fret node text, black] at (\s0) {\nodetext}; \else \pgfkeys{@fretnum=\num} \node[string=fretted, fret node text] at (\s\fretnum) {\nodetext}; \fi % Display the "text below" \ifnum\cb@textbelow>0 \if1\cb@textbelow \if\frettext\empty \else \node[below] at (\s) {\frettext}; \fi \else % Insert vphantom here to align all pitch names \node[below, pitch text below] at (\s) {\vphantom{\pgfkeys{@replace symbols=\#b}}\pitch}; \fi \fi \else % Anything other than a number is taken to mean "muted" \node[string=muted] at (\s0) {}; \fi } }{% \end{tikzpicture} } % Draw a chord box without barres, for example: % \chordbox{Am}{x,0,2,2,1,0} % \chordbox[5]{A}{5,7,7,6,5,5} \providecommand{\chordbox}[3][1]{% \begin{chordboxenv}{#1}{#2}{#3} \end{chordboxenv} } % Draw a chord box for a barre chord. Extra argument for the fret number(s) % whose notes should be barred, for example: % \bchordbox[3]{C}{x,3,5,5,5,3}{3,5} \providecommand{\bchordbox}[4][1]{% \begin{chordboxenv}{#1}{#2}{#3} \foreach \b in {#4} { \pgfkeys{@start barre=true, @fretnum=\b} \foreach[count=\s] \f in {#3} { \if\f\b \ifcb@startbarre \coordinate (start) at (\s\fretnum); \global\cb@startbarrefalse \else \coordinate (end) at (\s\fretnum); \fi \fi } \scoped[on background layer] \pgfkeys{draw barre={start}{end}}; } \end{chordboxenv} } \endinput [2018/12/07 v0.3 Support for pitch info] [2018/12/04 v0.2 Support for fingering info, further customisation] [2018/12/01 v0.1 Initial release]