%% 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