%% file: chordbars.sty %% Copyright 2018-2024 M. Sebastien Kramm % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3c % 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 M. Sebastien Kramm % % This work consists of the files chordbars.sty and chordbars_manual.tex % Home page: https://github.com/skramm/chordbars % LOG: % - 20240302: bugfixes with ycoef (version 1.3.2) % - 20230331: added "ycoeff" parameter (version 1.3.1) % - 2020525 % - added \addMeasures command % - added starred version of chordbar environment % TODO define command to have 1 chord per beat \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{chordbars}[2024-03-02 version 1.3.2] \RequirePackage{tikz} \RequirePackage{pgfmath} \RequirePackage{tkz-euclide} \usetikzlibrary{math,shapes} \RequirePackage{calc} \RequirePackage{ifthen} \RequirePackage{wasysym} % for \fullmoon \RequirePackage{relsize} % added on 2020-01-18 \def\vspacebefore{1ex} \def\vspaceafter{1ex} % This \dim command is used for diminished chords (until we find a nicer alternative) \def\dim{\fullmoon} \def\MajS{$\Delta$} \def\addN{\relscale{0.8}\mdseries add9} \def\susF{\relscale{0.8}\mdseries sus4} %\def\add4{\relscale{0.8}\mdseries add4} \newcommand{\songtitle} { %\tikzstyle{block} = [draw, rectangle, fill=blue!50,, text centered, minimum height=8mm,node distance=10em] \begin{center}% \begin{tikzpicture}[line width=1.5pt] \tikzstyle{block} = [rectangle, draw, text width=30em, text centered, minimum height=4em] % \tikzstyle{block} = [rectangle, draw, text centered, minimum height=4em] % \tikzstyle{block} = [rectangle, draw, minimum height=4em] \node [block,font=\fontsize{20}{28}\selectfont\bfseries] (init) { \@title\\ \@author }; \end{tikzpicture} \end{center}% \par \vskip 1.5em } \newcounter{NumMesure} \newcounter{NumPart} \newcounter{CurrentBarInLine} \newcounter{CurrentBar} \newcounter{CurrentLine} \xdef\tempoBPM{100} \newcommand{\bpm}[1] { \xdef\tempoBPM{#1} \rightline{Tempo=#1 BPM} } % "Beats Per Bar" % default value \xdef\bpb{4} \newcommand{\bpbfour} { \xdef\bpb{4} } \newcommand{\bpbthree} { \xdef\bpb{3} } \newcommand{\resetchordbars} { \setcounter{NumMesure}{0} \setcounter{NumPart}{0} \setcounter{CurrentBarInLine}{0} } \newcommand{\addMeasures}[1] { \addtocounter{NumMesure}{#1} \setcounter{NumPart}{0} \setcounter{CurrentBarInLine}{0} } \newcommand{\printNbBars} { \ifthenelse{\boolean{printBarNumber}} { Total number of bars: \arabic{NumMesure}, duration=\pgfmathparse{\theNumMesure/\tempoBPM*60*\bpb}\pgfmathresult {} s. }{} } % This boolean will be used to adjust horizontal position of the % number of repetitions when a half bar is added (see \addHalfBar) \newboolean{hasHalfBar} %\setboolean{hasHalfBar}{false} \newboolean{printBarNumber} \newcommand{\countbarsYes} { \setboolean{printBarNumber}{true} } \newcommand{\countbarsNo} { \setboolean{printBarNumber}{false} } \def\barsize{1.6}% \def\ycoeff{0.8}% \def\delta{0.36} \def\chordFontSize{\normalsize \bfseries} \def\titleFontSize{\large \bfseries} \xdef\NumberOfBarsPerLine{4} % arg1: chord % arg2: number of bars % arg3: title \newcommand{\chordline}[3] { {\fontfamily{phv}\selectfont \noindent\ignorespaces % \vspace{\vspacebefore} \refstepcounter{NumMesure}% \refstepcounter{NumPart}% \begin{tikzpicture}[line width=1pt,x=1cm,y=-1cm] % draw part title \ifthenelse {\boolean{printBarNumber}} { \draw (0,-\barsize*.2) node [anchor=west, align=left,font=\titleFontSize] {- Part \theNumPart: #3}; \draw (-.3,.5*\barsize) node {\bf \theNumMesure}; } { \draw (0,-\barsize*.2) node [anchor=west, align=left,font=\titleFontSize] {#3}; } \draw (0,0) -- (#2*\barsize,0); % horizontal lines \draw (0,\barsize*\ycoeff) -- (#2*\barsize,\barsize*\ycoeff); \draw (0,0) -- (0,\barsize*\ycoeff); % first vertical line \draw (\barsize,0) -- (\barsize,\barsize*\ycoeff); % second vertical line \draw (\barsize/2,\ycoeff*\barsize/2) node [font=\chordFontSize]{#1}; % chord name \foreach \k in {2,...,{#2}} { \draw (\k*\barsize,0) -- (\k*\barsize,\barsize*\ycoeff); \pgfmathsetmacro{\Axa}{(\k-1)*\barsize+\delta*\barsize} \pgfmathsetmacro{\Axb}{\k*\barsize-\delta*\barsize} \pgfmathsetmacro{\Aya}{(1-\delta)*\barsize*\ycoeff} \pgfmathsetmacro{\Ayb}{\delta*\barsize*\ycoeff} \coordinate (A) at (\Axa,\Ayb); \coordinate (B) at (\Axb,\Aya); \fill (A) circle[radius=2pt]; \fill (B) circle[radius=2pt]; \draw [thick] (\Axa,\Aya) -- (\Axb,\Ayb); % Draw "repeat" symbol } \end{tikzpicture} } \addtocounter{NumMesure}{#2} \addtocounter{NumMesure}{-1} } %========================================================================== % main environment, has 2 mandatory arguments % arg 1 (#2 inside): total number of 4 beat bars (4, 8, ...) % arg 2 {#3 inside}: part name (can be empty) % optional arg: nb of repetitions (default is 1) % starred version: does not print the grid ! Only does the counters update, and prints these \newenvironment{chordbar*}[3][1] { \refstepcounter{NumPart} \refstepcounter{NumMesure} \@ifundefined{c@TmpA}{\newcounter{TmpA}}{} \setcounter{TmpA}{#1*#2+\value{NumMesure}-1} \@ifundefined{c@TmpB}{\newcounter{TmpB}}{} \setcounter{TmpB}{#1*#2} \fontfamily{phv}\selectfont \noindent\ignorespaces % % \vspace{\vspacebefore} \begin{tikzpicture} \ifthenelse {\boolean{printBarNumber}} {\pgfmathsetmacro{\xpos}{0.6}} {\pgfmathsetmacro{\xpos}{0}} \draw (0,0) node {}; % to align with other environments of the page % if we have repetitions, we print it and also the total number of bars \ifnum#1=1 {\draw (\xpos,-\barsize*.2) node [anchor=west, align=left,font=\titleFontSize] {- Part \theNumPart: #3, #2 bars, [ \theNumMesure {} $\rightarrow$ \theTmpA {} ] }; } \else {\draw (\xpos,-\barsize*.2) node [anchor=west, align=left,font=\titleFontSize] {- Part \theNumPart: #3, #2 bars $\times$ #1 (\theTmpB), [ \theNumMesure {} $\rightarrow$ \theTmpA {} ] }; } \fi \end{tikzpicture} \setcounter{NumMesure}{\value{TmpA}} } \newenvironment{chordbar}[3][1] { % "newline" command: just switches to next line \newcommand{\newchordline} { \setcounter{CurrentBarInLine}{0} \refstepcounter{CurrentLine} } \newcommand{\chordf}[1]% { \ifthenelse {\theCurrentBarInLine=\NumberOfBarsPerLine} { \refstepcounter{CurrentLine} \setcounter{CurrentBarInLine}{0} } {} \refstepcounter{CurrentBarInLine}% \pgfmathsetmacro{\x}{-\barsize/2+\theCurrentBarInLine*\barsize} \pgfmathsetmacro{\y}{\value{CurrentLine})*\barsize*\ycoeff+\barsize*\ycoeff/2} \draw (\x,\y) node [font=\chordFontSize]{##1};% }% \newcommand{\chordh}[2]% { \ifthenelse {\theCurrentBarInLine=\NumberOfBarsPerLine} { \refstepcounter{CurrentLine} \setcounter{CurrentBarInLine}{0} } {} \refstepcounter{CurrentBarInLine}% % \typeout{CurrentBarInLine=\theCurrentBarInLine} \draw ( % {\barsize*(\theCurrentBarInLine-1)}, % {(\theCurrentLine+1)*\barsize*\ycoeff} % ) % -- % ( % {\theCurrentBarInLine*\barsize}, % {\theCurrentLine*\barsize*\ycoeff} % ); \draw ( % print first chord {-3*\barsize/4+\theCurrentBarInLine*\barsize}, {\theCurrentLine*\barsize*\ycoeff+1*\barsize/4*\ycoeff} ) node [font=\chordFontSize]{##1}; \draw ( % print second chord {-\barsize/4+\theCurrentBarInLine*\barsize}, {\theCurrentLine*\barsize*\ycoeff+3*\barsize/4*\ycoeff} ) node [font=\chordFontSize]{##2};% } \newcommand{\repeatBar}% { % \ifthenelse {\theCurrentBarInLine=\NumberOfBarsPerLine} { \refstepcounter{CurrentLine} \setcounter{CurrentBarInLine}{0} } {} \refstepcounter{CurrentBarInLine}% \pgfmathsetmacro{\Axa}{(\theCurrentBarInLine-1)*\barsize+\delta*\barsize} \pgfmathsetmacro{\Axb}{\theCurrentBarInLine*\barsize-\delta*\barsize} \pgfmathsetmacro{\Aya}{(1-\delta)*\barsize*\ycoeff+\theCurrentLine*\barsize*\ycoeff} \pgfmathsetmacro{\Ayb}{\delta*\barsize*\ycoeff+\theCurrentLine*\barsize*\ycoeff} \coordinate (A) at (\Axa,\Ayb); \coordinate (B) at (\Axb,\Aya); \fill (A) circle[radius=2pt]; \fill (B) circle[radius=2pt]; \draw [thick] (\Axa,\Aya) -- (\Axb,\Ayb); % }% \newcommand{\repeatBarPair}% { % \pgfmathsetmacro{\Axa}{\theCurrentBarInLine*\barsize+\delta*\barsize} \pgfmathsetmacro{\Axb}{(\theCurrentBarInLine+2)*\barsize-\delta*\barsize} \pgfmathsetmacro{\Aya}{(1-\delta)*\barsize*\ycoeff+\theCurrentLine*\barsize*\ycoeff} \pgfmathsetmacro{\Ayb}{\delta*\barsize*\ycoeff+\theCurrentLine*\barsize*\ycoeff} \coordinate (A) at (\Axa,\Ayb); \coordinate (B) at (\Axb,\Aya); \fill (A) circle[radius=2pt]; \fill (B) circle[radius=2pt]; \draw [thick] (\Axa,\Aya) -- (\Axb,\Ayb); % % \refstepcounter{CurrentBarInLine} \refstepcounter{CurrentBarInLine} \ifnum\value{CurrentBarInLine}=#2 { \refstepcounter{CurrentLine} \setcounter{CurrentBarInLine}{0} } \fi }% \newcommand{\addHalfBar}[1]% { \setboolean{hasHalfBar}{true} % % The part might have some repetitions (arg 1), so we need to increment % NumMesure by the number of repetions \addtocounter{NumMesure}{#1} % \refstepcounter{CurrentBarInLine}% % diagonal line % \draw (\xa,\ya) -- (\xb,\yb); A BUG HERE: investigate \draw (\theCurrentBarInLine*\barsize,{\theCurrentLine*\barsize*\ycoeff}) -- ({(\theCurrentBarInLine-1)*\barsize},{(\theCurrentLine+1)*\barsize*\ycoeff}); % horizontal line \draw (\theCurrentBarInLine*\barsize,{\theCurrentLine*\barsize*\ycoeff}) -- ({(\theCurrentBarInLine-1)*\barsize},{(\theCurrentLine)*\barsize*\ycoeff}); \pgfmathsetmacro{\x}{-3*\barsize/4+\theCurrentBarInLine*\barsize} \pgfmathsetmacro{\y}{\value{CurrentLine})*\barsize*\ycoeff+\barsize/4} \draw (\x,\y) node [font=\chordFontSize]{##1};% } % HERE beginning of environment code % \typeout{chordbar: START #3} \fontfamily{phv}\selectfont \setcounter{CurrentLine}{0} \setcounter{CurrentBarInLine}{0} \setcounter{CurrentBar}{0} % \setboolean{hasHalfBar}{true} \setboolean{hasHalfBar}{false} \refstepcounter{NumPart}% \refstepcounter{NumMesure}% \noindent\ignorespaces % \vspace{\vspacebefore} %\resizebox{8cm}{!} { % \scalebox{2}{ \begin{tikzpicture}[line width=1pt,x=1cm,y=-1cm] %,scale=2] \ifthenelse {\boolean{printBarNumber}} {\draw (-.3,.5*\barsize) node{\bf \theNumMesure};} {} % compute the number of bars of the first line \xdef\NbBarsInitialLine{\NumberOfBarsPerLine} \ifthenelse {#2<\NumberOfBarsPerLine} {\xdef\NbBarsInitialLine{#2}} {} % initial horizontal line \draw (0,0) -- (\NbBarsInitialLine*\barsize,0); % draw part title \ifthenelse {\boolean{printBarNumber}} {\draw (0,-\barsize*.2) node [anchor=west, align=left,font=\titleFontSize] {- Part \theNumPart: #3};} {\draw (0,-\barsize*.2) node [anchor=west, align=left,font=\titleFontSize] {- #3};} \pgfmathtruncatemacro{\nblines}{(#2-1)/\NumberOfBarsPerLine+1} % \typeout{chordbarl: nblines=\nblines} \foreach \line in {1,...,\nblines} { \draw (0,{\barsize*\ycoeff*(\line-1)}) -- (0,\line*\barsize*\ycoeff); % first vertical line \xdef\nbbars{\NumberOfBarsPerLine} \ifnum\line=\nblines { \pgfmathtruncatemacro{\nbbars}{#2-\NumberOfBarsPerLine*(\nblines-1)} \xdef\nbbars{\nbbars} } \fi % \typeout{chordbarl: nbbars=\nbbars} \foreach \k in {1,...,{\nbbars}} { \draw (\k*\barsize,{(\line-1)*\barsize*\ycoeff}) -- (\k*\barsize,{\line*\barsize*\ycoeff}); \draw (0,{\line*\barsize*\ycoeff}) -- (\k*\barsize,{\line*\barsize*\ycoeff}); \refstepcounter{CurrentBar}% } } \setcounter{NumMesure}{#1*#2+\value{NumMesure}-1} % print the number of repetitions \ifnum#1=1 {} % do nothing \else %-------------------- % THIS HERE IS WIP ! \ifthenelse {\boolean{hasHalfBar}} {\def\xoffset{2.0}} {\def\xoffset{1.5}} %-------------------- \ifthenelse {\boolean{printBarNumber}} {\draw (\NbBarsInitialLine*\barsize+\xoffset,0.5*\barsize) node {\Large \bf $\times$~#1};} {} \fi }% { %\typeout{chordbar: END} \end{tikzpicture} % } % % \par\noindent% % \ignorespacesafterend \vspace{\vspaceafter} } % REMOVE INDENTATION \setlength\parindent{0pt} % so the user can use # without escaping % see https://tex.stackexchange.com/questions/467562 \AtBeginDocument{\catcode`#=12 } % additional code: redefine sharp and flat in text mode % from https://tex.stackexchange.com/a/422249/11083 \let\OLDsharp\sharp \renewcommand{\sharp}{\ensuremath{\OLDsharp}} \let\OLDflat\flat \renewcommand{\flat}{\ensuremath{\OLDflat}} \endinput