6

The basis for my question: How to make or add options for packages or functions

Is it possible to make it so that one could write numbers in the circles, like so?:

example

Here is a minimal example showing the above without the numbering:

\documentclass{article}
\usepackage{piano}
\begin{document}

\keyboard[Co][Eo][Gso][Ct][Et]

\end{document}
  • Could you provide the community with something that replicates the output without the numbers - a minimal working example (MWE)? That'll give a good foundation to start from, rather than creating something from scratch. – Werner May 21 '15 at 19:35
  • This is certainly possible, but looking at piano.sty, it seems you'd have to more or less completely redefine the \keyboard command. A relatively simple regex would do it, but you'd need the altered piano.sty in your TeX tree. Change the name while you're at it, to comply with the license. – dgoodmaniii May 21 '15 at 19:47
  • Added the mwe from the readme provided in the link. I'm at a complete loss at what to do. Helpz! – Buschmann May 21 '15 at 20:03
  • I have a modified piano.sty and maybe it's possible to add the numbers. Can you tell how they should be defined? Are they just in sequence from the left? – egreg May 21 '15 at 20:32
  • I have one that adds the numbers in sequence from the left, but they're not centered because I don't really get the picture environment. – dgoodmaniii May 21 '15 at 20:33
11

Here's a modified version of piano.sty that adds also the function you ask for.

Also the syntax is changed, but I believe it's better than adding a bunch of optional arguments.

xpiano.sty

\ProvidesPackage{xpiano}[2015/05/21 from piano.sty by Émile Daneault]
\RequirePackage{xcolor}
\usepackage{xparse}

\definecolor{pianodefault}{RGB}{255,127,0}

\ExplSyntaxOn
\NewDocumentCommand{\keyboard}{ m }
 {
  \piano_keyboard:n { #1 }
 }

\keys_define:nn { piano }
 {
  numbers .bool_set:N = \l_piano_numbers_bool,
  color   .tl_set:N  = \l_piano_color_tl,
  one     .tl_set:N  = \l_piano_one_tl,
  two     .tl_set:N  = \l_piano_two_tl,
  three   .tl_set:N  = \l_piano_three_tl,
  four    .tl_set:N  = \l_piano_four_tl,
  five    .tl_set:N  = \l_piano_five_tl,
  six     .tl_set:N  = \l_piano_six_tl,
  seven   .tl_set:N  = \l_piano_seven_tl,
  numbers .initial:n = false,
  color   .initial:n = {pianodefault},
  one     .initial:n = {},
  two     .initial:n = {},
  three   .initial:n = {},
  four    .initial:n = {},
  five    .initial:n = {},
  six     .initial:n = {},
  seven   .initial:n = {},
 }

\cs_new_protected:Npn \piano_keyboard:n #1
 {
  \group_begin:
  \keys_set:nn { piano } { #1 }
  %% Clavier 2 octaves
  \setlength{\unitlength}{0.5cm}
  \begin{picture}(15,4.5)
  %Touches blanches
  \multiput(0,0)(1,0){14}{\line(0,1){4}}

  %Contour
  \put(0,0){\line(0,1){4}}
  \put(0,0){\line(1,0){14}}
  \put(14,0){\line(0,1){4}}
  \put(0,4){\line(1,0){14}}

  %Touches noires
  \linethickness{3mm}
  \multiput(1,4)(1,0){2}{\line(0,-1){3}}
  \multiput(4,4)(1,0){3}{\line(0,-1){3}}
  \multiput(8,4)(1,0){2}{\line(0,-1){3}}
  \multiput(11,4)(1,0){3}{\line(0,-1){3}}
  %Rond de note
  \color{\l_piano_color_tl}
  \__piano_do_key:N \l_piano_one_tl
  \__piano_do_key:N \l_piano_two_tl
  \__piano_do_key:N \l_piano_three_tl
  \__piano_do_key:N \l_piano_four_tl
  \__piano_do_key:N \l_piano_five_tl
  \__piano_do_key:N \l_piano_six_tl
  \__piano_do_key:N \l_piano_seven_tl

  \end{picture}
  \group_end:
 }

\cs_new_protected:Npn \__piano_add_note:nn #1 #2
 {
  \put(#2){\circle*{0.5}}
  \bool_if:NT \l_piano_numbers_bool
   {
    \put(#2){\makebox(0,0){\color{black}\tiny#1}}
   }
 }

\cs_new_protected:Npn \__piano_do_key:N #1
 {
  \str_case:Vn #1
   {
    {}{}% initial case
    {Co}{\__piano_add_note:nn {0}{0.5,0.5}}
    {Do}{\__piano_add_note:nn {2}{1.5,0.5}}
    {Eo}{\__piano_add_note:nn {4}{2.5,0.5}}
    {Fo}{\__piano_add_note:nn {5}{3.5,0.5}}
    {Go}{\__piano_add_note:nn {7}{4.5,0.5}}
    {Ao}{\__piano_add_note:nn {9}{5.5,0.5}}
    {Bo}{\__piano_add_note:nn {11}{6.5,0.5}}
    {Ct}{\__piano_add_note:nn {0}{7.5,0.5}}
    {Dt}{\__piano_add_note:nn {2}{8.5,0.5}}
    {Et}{\__piano_add_note:nn {4}{9.5,0.5}}
    {Ft}{\__piano_add_note:nn {5}{10.5,0.5}}
    {Gt}{\__piano_add_note:nn {7}{11.5,0.5}}
    {At}{\__piano_add_note:nn {9}{12.5,0.5}}
    {Bt}{\__piano_add_note:nn {11}{13.5,0.5}}
    {Cso}{\__piano_add_note:nn {1}{1,1.5}}
    {Dso}{\__piano_add_note:nn {3}{2,1.5}}
    {Fso}{\__piano_add_note:nn {6}{4,1.5}}
    {Gso}{\__piano_add_note:nn {8}{5,1.5}}
    {Aso}{\__piano_add_note:nn {10}{6,1.5}}
    {Cst}{\__piano_add_note:nn {1}{8,1.5}}
    {Dst}{\__piano_add_note:nn {3}{9,1.5}}
    {Fst}{\__piano_add_note:nn {6}{11,1.5}}
    {Gst}{\__piano_add_note:nn {8}{12,1.5}}
    {Ast}{\__piano_add_note:nn {10}{13,1.5}}
   }
 }

\cs_generate_variant:Nn \str_case:nn { V }
\ExplSyntaxOff

Test file

\documentclass{article}
\usepackage{xpiano}

\definecolor{pianoyellow}{RGB}{127,127,0}

\begin{document}
\keyboard{
  numbers,
  color=red!20,
  one=Co,
  two=Eo,
  three=Gso,
  four=Bo,
  five=Ct
}

\bigskip

\keyboard{
  color=red!20,
  one=Co,
  two=Eo,
  three=Gso,
  four=Bo,
  five=Ct
}

\bigskip

\keyboard{
  one=Cso,
  two=Fso,
}

\bigskip

\keyboard{
  color=pianoyellow,
  one=Cso,
  two=Fso,
}

\end{document}

Output

enter image description here


Extended version

The keys font, size and single have been added. The default of size is 0.5cm (like in the original). The default for font is \tiny. With single one specifies a single octave (from C to B).

Also ext can be used, which adds an additional C at the far right, but which is probably only meaningful together with single, as there's no name for that note with double octave (it could be added, though).

Finally height can be set; the default value is 4, that is, four times the width of the keys.

In this version, instead of 10 and 11 for B flat and B, t and e are produced. A command \keyboardsetup allows to set the values of the parameters not related to producing notes (respecting grouping). So you can set in the preamble something like

\keyboardsetup{
  single,
  size=2cm,
  numbers
}

and all \keyboard commands will use those values and it won't be necessary to specify them.

xpiano.sty

\ProvidesPackage{xpiano}[2015/05/21 from piano.sty by Émile Daneault]
\RequirePackage{xcolor}
\RequirePackage{xparse}

\definecolor{pianodefault}{RGB}{255,127,0}

\ExplSyntaxOn
\NewDocumentCommand{\keyboard}{ m }
 {
  \piano_keyboard:n { #1 }
 }
\NewDocumentCommand{\keyboardsetup}{ m }
 {
  \keys_set:nn { piano } { #1 }
 }

\keys_define:nn { piano }
 {
  font    .tl_set:N   = \l_piano_fontsize_tl,
  single  .bool_set:N = \l_piano_single_bool,
  ext     .bool_set:N = \l_piano_ext_bool,
  size    .dim_set:N  = \l_piano_size_dim,
  height  .tl_set:N   = \l_piano_height_tl,
  numbers .bool_set:N = \l_piano_numbers_bool,
  color   .tl_set:N   = \l_piano_color_tl,
  one     .tl_set:N   = \l_piano_one_tl,
  two     .tl_set:N   = \l_piano_two_tl,
  three   .tl_set:N   = \l_piano_three_tl,
  four    .tl_set:N   = \l_piano_four_tl,
  five    .tl_set:N   = \l_piano_five_tl,
  six     .tl_set:N   = \l_piano_six_tl,
  seven   .tl_set:N   = \l_piano_seven_tl,
  font    .initial:n  = \tiny,
  single  .initial:n  = false,
  single  .default:n  = true,
  ext     .initial:n  = false,
  ext     .default:n  = true,
  size    .initial:n  = 0.5cm,
  height  .initial:n  = 4,
  numbers .initial:n  = false,
  numbers .default:n  = true,
  color   .initial:n  = {pianodefault},
  one     .initial:n  = {},
  two     .initial:n  = {},
  three   .initial:n  = {},
  four    .initial:n  = {},
  five    .initial:n  = {},
  six     .initial:n  = {},
  seven   .initial:n  = {},
 }

\tl_new:N \l__piano_width_tl

\cs_new_protected:Npn \piano_keyboard:n #1
 {
  \group_begin:
  \keys_set:nn { piano } { #1 }
  \bool_if:NTF \l_piano_ext_bool
   {
    \tl_set:Nx \l__piano_width_tl
     {
      \bool_if:NTF \l_piano_single_bool { 8 } { 15 }
     }
   }
   {
    \tl_set:Nx \l__piano_width_tl
     {
      \bool_if:NTF \l_piano_single_bool { 7 } { 14 }
     }
   }

  %% Clavier 2 octaves
  \setlength{\unitlength}{\l_piano_size_dim}
  \begin{picture}(\l__piano_width_tl,\l_piano_height_tl)
  %Touches blanches
  \multiput(0,0)(1,0){\l__piano_width_tl}{\line(0,1){\l_piano_height_tl}}

  %Contour
  \put(0,0){\line(0,1){\l_piano_height_tl}}
  \put(0,0){\line(1,0){\l__piano_width_tl}}
  \put(\l__piano_width_tl,0){\line(0,1){\l_piano_height_tl}}
  \put(0,\l_piano_height_tl){\line(1,0){\l__piano_width_tl}}

  %Touches noires
  \linethickness{.6\l_piano_size_dim}
  \multiput(1,\l_piano_height_tl)(1,0){2}{\line(0,-1){\fp_eval:n {0.67*\l_piano_height_tl}}}
  \multiput(4,\l_piano_height_tl)(1,0){3}{\line(0,-1){\fp_eval:n {0.67*\l_piano_height_tl}}}
  \bool_if:NF \l_piano_single_bool
   {
    \multiput(8,\l_piano_height_tl)(1,0){2}{\line(0,-1){\fp_eval:n {0.67*\l_piano_height_tl}}}
    \multiput(11,\l_piano_height_tl)(1,0){3}{\line(0,-1){\fp_eval:n {0.67*\l_piano_height_tl}}}
   }
  %Rond de note
  \color{\l_piano_color_tl}
  \__piano_do_key:N \l_piano_one_tl
  \__piano_do_key:N \l_piano_two_tl
  \__piano_do_key:N \l_piano_three_tl
  \__piano_do_key:N \l_piano_four_tl
  \__piano_do_key:N \l_piano_five_tl
  \__piano_do_key:N \l_piano_six_tl
  \__piano_do_key:N \l_piano_seven_tl

  \end{picture}
  \group_end:
 }

\cs_new_protected:Npn \__piano_add_note:nn #1 #2
 {
  \put(#2){\circle*{0.5}}
  \bool_if:NT \l_piano_numbers_bool
   {
    \put(#2){\makebox(0,0){\color{black}\l_piano_fontsize_tl #1}}
   }
 }

\cs_new_protected:Npn \__piano_do_key:N #1
 {
  \str_case:Vn #1
   {
    {}{}% initial case
    {Co}{\__piano_add_note:nn {0}{0.5,0.5}}
    {Do}{\__piano_add_note:nn {2}{1.5,0.5}}
    {Eo}{\__piano_add_note:nn {4}{2.5,0.5}}
    {Fo}{\__piano_add_note:nn {5}{3.5,0.5}}
    {Go}{\__piano_add_note:nn {7}{4.5,0.5}}
    {Ao}{\__piano_add_note:nn {9}{5.5,0.5}}
    {Bo}{\__piano_add_note:nn {$e$}{6.5,0.5}}
    {Ct}{\__piano_add_note:nn {0}{7.5,0.5}}
    {Dt}{\__piano_add_note:nn {2}{8.5,0.5}}
    {Et}{\__piano_add_note:nn {4}{9.5,0.5}}
    {Ft}{\__piano_add_note:nn {5}{10.5,0.5}}
    {Gt}{\__piano_add_note:nn {7}{11.5,0.5}}
    {At}{\__piano_add_note:nn {9}{12.5,0.5}}
    {Bt}{\__piano_add_note:nn {$e$}{13.5,0.5}}
    {Cso}{\__piano_add_note:nn {1}{1,\fp_eval:n {0.5+0.33*\l_piano_height_tl}}}
    {Dso}{\__piano_add_note:nn {3}{2,\fp_eval:n {0.5+0.33*\l_piano_height_tl}}}
    {Fso}{\__piano_add_note:nn {6}{4,\fp_eval:n {0.5+0.33*\l_piano_height_tl}}}
    {Gso}{\__piano_add_note:nn {8}{5,\fp_eval:n {0.5+0.33*\l_piano_height_tl}}}
    {Aso}{\__piano_add_note:nn {$t$}{6,\fp_eval:n {0.5+0.33*\l_piano_height_tl}}}
    {Cst}{\__piano_add_note:nn {1}{8,\fp_eval:n {0.5+0.33*\l_piano_height_tl}}}
    {Dst}{\__piano_add_note:nn {3}{9,\fp_eval:n {0.5+0.33*\l_piano_height_tl}}}
    {Fst}{\__piano_add_note:nn {6}{11,\fp_eval:n {0.5+0.33*\l_piano_height_tl}}}
    {Gst}{\__piano_add_note:nn {8}{12,\fp_eval:n {0.5+0.33*\l_piano_height_tl}}}
    {Ast}{\__piano_add_note:nn {$t$}{13,\fp_eval:n {0.5+0.33*\l_piano_height_tl}}}
   }
 }

\cs_generate_variant:Nn \str_case:nn { V }
\ExplSyntaxOff

Test file

\documentclass{article}
\usepackage{xpiano}

\definecolor{pianoyellow}{RGB}{127,127,0}

\begin{document}

\setlength{\unitlength}{2pt}

\keyboard{
  numbers,
  height=3,
  color=red!20,
  one=Co,
  two=Eo,
  three=Gso,
  four=Bo,
  five=Ct
}

\bigskip

\keyboard{
  ext,
  color=red!20,
  one=Co,
  two=Eo,
  three=Gso,
  four=Bo,
  five=Ct
}

\bigskip

\keyboard{
  single,
  ext,
  height=3,
  numbers,
  font=\small,
  size=1cm,
  one=Cso,
  two=Fso,
  three=Aso,
  four=Ct,
}

\bigskip

\keyboard{
  color=pianoyellow,
  one=Cso,
  two=Fso,
}

\end{document}

Output

enter image description here

  • Brilliant! Is it possible to adjust it so C=0? – Buschmann May 21 '15 at 21:09
  • @Buschmann I'm not sure to understand. What should the number represent? – egreg May 21 '15 at 21:11
  • 1
    @Buschmann Now it should be what you're asking for. – egreg May 21 '15 at 21:22
  • 1
    Thank you so much! And now, for the encore drum roll is it possible to adjust the size of the thing? Or, make it just one octave? – Buschmann May 21 '15 at 21:25
  • 1
    @Buschmann Now there's also the ext key that adds a final C (both with single and double octave). I have also fixed the width and height of the picture. – egreg May 21 '15 at 22:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.