Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

Is there a package or macro that allows me to easily typeset musical pitches, like the following:

enter image description here

? Indeed I would like to have subscripts for the octaves. Let's say

$\mathrm{E}\flat_3$

How would I write a macro producing this output, when the invocation is

\note{Eb3}

Like:

\newcommand{\note}[1]{???}

I would have to take the string apart, the first char goes into \mathrm, then there is an optional second char # or b, followed by a digit.

share|improve this question
1  
Do you know this ctan.org/pkg/musictex ? –  Sigur Dec 4 '13 at 15:37
    
I read about musictex. I don't want to typeset scores, I use Lilypond for that. Also it says it's for TeX not LaTeX. I just need to have some inline functions such as the note names above. –  Emit Taste Dec 4 '13 at 18:30

2 Answers 2

up vote 18 down vote accepted

The only quirk is that you have to use brackets [] rather than braces {} to enclose the argument.

\documentclass{article}
\def\note[#1#2#3]{#1\if b#2$\flat_#3$\else\if#2##$\sharp_#3$\else$_#2$\fi\fi}
\begin{document}
\note[Eb3]
\note[A2]
\note[F#4]
\end{document}

enter image description here

If you would prefer the use of braces to brackets, then the following modification would do. It renames the \note from the above code as \xnote and creates a newcommand \note to do the argument translation.

\documentclass{article}
\newcommand\note[1]{\xnote[#1]}
\def\xnote[#1#2#3]{#1\if b#2$\flat_#3$\else\if#2##$\sharp_#3$\else$_#2$\fi\fi}
\begin{document}
\note{Eb3}
\note{A2}
\note{F#4}
\end{document}

Since egreg's answer seems to go beyond what the OP asked, providing reasonable behavior when either argument 2, argument 3, or arguments 2 and 3 are missing, I felt it incumbent to do the same (EDITED using Qrrbrrbr...brbrbrl's suggestion to enclose subscript definitions in braces, which will facilitate two-digit octave numbers, shown in last line of output):

\documentclass{article}
\newcommand\note[1]{\xnote#1\relax\relax\relax}
\def\xnote#1#2#3\relax{#1\if#2\relax\else\if b#2$\flat\if#3\relax%
  \else_{#3}\fi$\else\if###2$\sharp\if#3\relax\else_{#3}\fi$\else$_{#2}$\fi\fi\fi}
\begin{document}
\note{Eb3}
\note{A2}
\note{C#}
\note{A}
\note{Eb}
\note{F#4}

\note{F{14}}
\note{F#{14}}
\end{document}

enter image description here

share|improve this answer
5  
How I like when an answer to a question asking for a package has only a few lines of code! :-) –  Przemysław Scherwentke Dec 4 '13 at 15:59
    
If you use _{#3} instead of _#3 (though I prefer \textsubscript) it would be possible to use \note{F#14} but 4 would be dropped if \node{F14} has been used. –  Qrrbrbirlbel Dec 4 '13 at 19:48
    
@Qrrbrbirlbel I revised, based on your suggestion. –  Steven B. Segletes Dec 5 '13 at 1:51

Some slow scanning of the argument is needed:

\documentclass{article}
\usepackage{fixltx2e} % for \textsubscript
\makeatletter
\newcommand{\note}[1]{\emit@note#1\@nil}
\def\emit@note#1#2\@nil{%
  \textup{#1}%
  \if\relax\detokenize{#2}\relax
    \expandafter\@gobble
  \else
    \expandafter\@firstofone
  \fi
  {\emit@@note#2\@nil}%
}
\def\emit@@note{\@ifnextchar##{\emit@sharp}{\emit@@@note}}
\def\emit@sharp#1{$\sharp$\emit@@@note}
\def\emit@@@note{\@ifnextchar b{$\flat$\emit@@@@note}{\emit@@@@note{}}}
\def\emit@@@@note#1#2\@nil{\textsubscript{#2}}
\makeatother

\begin{document}

\note{A}
\note{A#}
\note{Ab}
\note{A2}
\note{A#2}
\note{Ab2}

\end{document}

enter image description here


By kind request, here's a possible LaTeX3 implementation:

\documentclass{article}
\usepackage{fixltx2e} % for \textsubscript

\usepackage{xparse}
\ExplSyntaxOn
% user level command
\NewDocumentCommand{\note}{m}
 {
  \emit_note:n { #1 }
 }

% a variable
\tl_new:N \l_emit_specs_tl

% internal main function
\cs_new_protected:Npn \emit_note:n #1
 {% Get the first token
  \emit_textup:x { \tl_head:n { #1 } }
  % Get the rest and pass control to \emit_do_specs:n
  \tl_set:Nx \l_emit_specs_tl { \tl_tail:n { #1 } }
  \tl_if_empty:NF \l_emit_specs_tl
   {
    \emit_do_specs:o { \l_emit_specs_tl \q_stop }
   }
 }

% We can't use \textup{ \tl_head:n { #1 } } because of possible #
\cs_new_protected:Npn \emit_textup:n #1
 {
  \textup { #1 }
 }
\cs_generate_variant:Nn \emit_textup:n { x }

% Check if the first token is # or b
% and take appropriate actions
% Then hand the remainder to \emit_range:w
\cs_new_protected:Npn \emit_do_specs:n #1
 {
  \peek_charcode_remove:NTF ##
   { $\sharp$ \emit_range:w }
   {
    \peek_charcode_remove:NTF b
     { $\flat$ \emit_range:w }
     { \emit_range:w }
   }
  #1
 }
\cs_generate_variant:Nn \emit_do_specs:n { o }

\cs_new_protected:Npn \emit_range:w #1 \q_stop
 {
  \tl_if_empty:nF { #1 } { \textsubscript{#1} }
 }
\ExplSyntaxOff

\begin{document}

\note{A}
\note{A#}
\note{Ab}
\note{A2}
\note{A#2}
\note{Ab2}

\end{document}
share|improve this answer
3  
No L3 version? Pleeeease. :) –  Paulo Cereda Dec 4 '13 at 18:05
    
Can you tell me what slow-scanning is, and if this much longer version has any advantages over the solution of Steven B. Segletes? –  Emit Taste Dec 4 '13 at 18:32
    
@EmitTaste You can also do \note{A#12}, with this. It's slow in the sense that I use \@ifnextchar to look at the next token. –  egreg Dec 4 '13 at 18:54
    
Ok, thanks! I will use this if I need double accidentals or higher octaves. –  Emit Taste Dec 4 '13 at 20:42
    
@EmitTaste For double accidentals one needs to extend the macros, but it wouldn't be difficult. –  egreg Dec 4 '13 at 20:48

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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