TEMPO: reproduce un sonido en GIF/PDF/SVG animado

TEMPO: reproduce un sonido en GIF/PDF/SVG animado

Al practicar piano,TEMPO(una aplicación en iOS, CHplay) es un metrónomo que a menudo se usa para marcar el tiempo.

Puedo crear GIF/PDF/SVG/cuadro animado (en beamer) para TEMPO, pero no sé cómo reproducir un sonido (por ejemplo, el pitido 8, mp3o wavenaquí) en cada latido.

¿Alguien puede ayudar (con el código completo y una explicación clara)? ¡Gracias!

ingrese la descripción de la imagen aquí

El siguiente código son mis MWE. (estos son buenos ejemplos de cosas animadas)

% TEMPO for piano tempo.tex
% for animated GIF, run on command line (require ImageMagick installed)
% magick -density 200 -delay 100 tempo.pdf tempo.gif
% -delay 100 >>> each frame is 100/100 = 1 second 
\documentclass[tikz]{standalone}
\begin{document}
\foreach \n in {1,...,4}{
\pagecolor{white}
\begin{tikzpicture}
\path (0,-1) rectangle (5,1);
\shade[inner color=green,outer color=green!10] 
(\n,0) circle(.5);
\foreach \i in {1,...,4}
\fill[cyan] (\i,0) circle(.3);
\end{tikzpicture}
}
\end{document}

Con pequeños cambios, podemos obtener un PDF animado (abrirlo en Acrobat Reader).

% animated PDF standalone tempopdf.tex
% \multiframe{4}{n=1+1} >>> starting frame is with n=1, 
% then plus 1 each frame, so we have 4 frames
% [loop,controls]{1} >>> number 1 means 1 second each frame
\documentclass{standalone}
\usepackage{tikz}
\usepackage{animate}
\begin{document}
\begin{animateinline}[loop,controls]{1}
\multiframe{4}{n=1+1}
{
\begin{tikzpicture}
\path (0,-1) rectangle (5,1);
\shade[inner color=green,outer color=green!10] 
(\n,0) circle(.6);
\foreach \i in {1,...,4}
\fill[cyan] (\i,0) circle(.3);
\end{tikzpicture}
}
\end{animateinline}
\end{document}

Marco PDF animado en Beamer (abrir con Acrobat Reader)

% animated PDF frame in beamer (open with Acrobat Reader)
\documentclass{beamer}
\usepackage{tikz}
\usepackage{animate}
\usepackage{multimedia}
\begin{document}
\begin{frame}{TEMPO for piano}
\begin{center}
\begin{animateinline}[loop,controls]{1}
\multiframe{4}{n=1+1}
{
\begin{tikzpicture}
\path (0,-1) rectangle (5,1);
\shade[inner color=green,outer color=green!10] (\n,0) circle(.6);
\foreach \i in {1,...,4} \fill[cyan] (\i,0) circle(.3);
\end{tikzpicture}
}
\end{animateinline}
\end{center}
\end{frame} 
\end{document}

Respuesta1

Hacer clicen la imagen a continuación para ver el metrónomo (versión SVG) en acción:

https://agrahn.gitlab.io/svg/tempoForWeb-2.1.svg

Este animateejemplo basado en - viene en dos versiones.

ElPDFLa versión requiere Acrobat Reader y, por lo tanto, está restringida a plataformas Windows y OSX para PC de escritorio. (Los dispositivos móviles no son compatibles). La versión PDF se utiliza media9para reproducir el archivo de sonido incrustado.click.mp3, tomado del animatepaquete que ya proporciona un ejemplo de metrónomo en su manual.

el independienteSVGLa versión se ejecuta en la mayoría de los navegadores web contemporáneos (Firefox, Chrome, Opera...), incluso en dispositivos móviles. Aquí, el sonido está incrustado como un Blob codificado en Base64 usando la <audio>etiqueta HTML5. ( click.mp3fue codificado con " base64 click.mp3" en la línea de comando). El archivo de sonido físicamente incrustado hace que el SVG sea autónomo.

En cualquier caso, JavaScript inicia la reproducción del sonido en cada cambio de fotograma de la animación en ejecución. La función "línea de tiempo" animatese utiliza para asociar el código JS con cada fotograma (entrada de línea de tiempo frames.txt).

El marcador de tempo se implementa con un segundo animateinlineentorno. Proporciona 39 velocidades típicas de metrónomo que se pueden controlar con los botones +/-. Los botones utilizan la animateinterfaz JavaScript para incrementar y disminuir el número de fotograma del marcador de tempo. Otro archivo de línea de tiempo, tempo.txtasocia cada fotograma marcador con un fragmento JS que escala la velocidad del metrónomo en consecuencia, nuevamente utilizando la interfaz JS de animate.

PDFversión, para ser compilada con pdflatex, lualatex, latex+dvips+ps2pdf, o xelatex:

\documentclass[varwidth,border=12pt]{standalone}

\usepackage{tikz}
\usepackage{animate}
\usepackage{media9}
\usepackage{fontawesome5}

% tempo markers
\def\tempos{{40,42,44,46,48,50,52,54,56,58,60,63,66,69,72,76,80,84,88,92,96,100,104,108,112,116,120,126,132,138,144,152,160,168,176,184,192,200,208}}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% timeline files
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% metronome
\usepackage{filecontents}
\begin{filecontents*}{frames.txt}
::0: annotRM['click'].callAS('play');
::1: annotRM['click'].callAS('play');
::2: annotRM['click'].callAS('play');
::3: annotRM['click'].callAS('play');
\end{filecontents*}
% tempo
\newwrite\TimeLineFile
\immediate\openout\TimeLineFile=tempo.txt
\foreach \i in {0,1,...,38} {
    %JavaScript for scaling the metronome's default speed (60 frames per min)
    \pgfmathparse{\tempos[\i]/60}
    \immediate\write\TimeLineFile{::\i:anim.metronome.speed=\pgfmathresult;}
}
\immediate\closeout\TimeLineFile
%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\setlength{\textwidth}{4.4cm}

\begin{document}
\begin{center}
%the sound player  
\makebox[0pt][r]{\includemedia[
  width=1ex,height=1ex,
  label=click,
  addresource=click.mp3,
  activate=pageopen,transparent,noplaybutton,
  flashvars={source=click.mp3&hideBar=true}
]{}{APlayer.swf}}%
\makebox[4cm][l]{The \LaTeX{} Metronome}\\[1ex]

%%%%%%%%%%%
% metronome
%%%%%%%%%%%
\begin{animateinline}[label=metronome,nomouse,loop,timeline=frames.txt]{1}
  \multiframe{4}{n=1+1}{
    \begin{tikzpicture}
      \path (0.3,-0.5) rectangle (4.7,0.5);
      \shade[inner color=green,outer color=green!10] (\n,0) circle(.6);
      \foreach \i in {1,...,4} \fill[cyan] (\i,0) circle(.3);
    \end{tikzpicture}
  }
\end{animateinline}

%%%%%%%%%%%
% controls
%%%%%%%%%%%
\makebox[4cm]{%
\mediabutton[
  jsaction={
    if(anim.metronome.isPlaying) anim.metronome.stopFirst(); 
    else anim.metronome.playFwd();
  }
]{\faPowerOff}\hfill
% tempo
\mediabutton[
  jsaction={ try {--anim.tempo.frameNum;} catch (e) {} }
]{\faMinusCircle}\,%
\begin{animateinline}[label=tempo,step,nomouse,poster=10,timeline=tempo.txt]{1}
  \multiframe{39}{i=0+1}{
    \pgfmathparse{\tempos[\i]}
    \makebox[\widthof{000}][c]{\strut\pgfmathresult}
  }
\end{animateinline}\,%
\mediabutton[
  jsaction={ try {++anim.tempo.frameNum;} catch (e) {} }
]{\faPlusCircle}}
\end{center}
\end{document}

SVGversión, para ser compilada con

latex tempoForWeb.tex
latex tempoForWeb.tex
dvisvgm --font-format=woff --exact --zoom=-1 tempoForWeb.dvi

El SVG se puede ver de forma independiente en un navegador web o incrustado en una página web mediante la <object>etiqueta HTML:

\documentclass[dvisvgm,varwidth,preview]{standalone}

\usepackage{tikz}
\usepackage{animate}
\usepackage{fontawesome5}

% tempo markers
\def\tempos{{40,42,44,46,48,50,52,54,56,58,60,63,66,69,72,76,80,84,88,92,96,100,104,108,112,116,120,126,132,138,144,152,160,168,176,184,192,200,208}}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% timeline files
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% metronome
\usepackage{filecontents}
\begin{filecontents*}{frames.txt}
::0:$('click').play();
::1:$('click').play();
::2:$('click').play();
::3:$('click').play();
\end{filecontents*}
% tempo
\newwrite\TimeLineFile
\immediate\openout\TimeLineFile=tempo.txt
\foreach \i in {0,1,...,38} {
    %JavaScript for scaling the metronome's default speed (60 frames per min)
    \pgfmathparse{\tempos[\i]/60}
    \immediate\write\TimeLineFile{::\i:anim.metronome.speed=\pgfmathresult;}
}
\immediate\closeout\TimeLineFile
%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% for producing push buttons
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\ExplSyntaxOn
\def\controlButton#1#2{% #1:button face, #2 JavaScript
  \sbox{0}{#1}
  \makebox[0pt][l]{\usebox{0}}
  \pbs_pdfannot:nnnn{\wd0}{\ht0}{\dp0}{cursor='pointer'~onmousedown='#2'}
  \phantom{\usebox{0}}
}
\ExplSyntaxOff
%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\setlength{\textwidth}{4.4cm}

\begin{document}
% embed sound
\special{dvisvgm:rawdef
  <audio xmlns="http://www.w3.org/1999/xhtml" id='click'>
    <source
    src="data:audio/mpeg;base64,
    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
    qqqqqqqqqqqq" type="audio/mpeg"/>
%    <source src="click.mp3" type="audio/mpeg"/> % alternatively: separate mp3
  </audio>
  <script type="text/javascript">
  <![CDATA[
    function $(id) {return document.getElementById(id);};
  ]]>
  </script>
}
\begin{center}
\makebox[4cm][l]{The \LaTeX{} Metronome}\\[1ex]

%%%%%%%%%%%
% metronome
%%%%%%%%%%%
\begin{animateinline}[label=metronome,nomouse,loop,timeline=frames.txt]{1}
  \multiframe{4}{n=1+1}{
    \begin{tikzpicture}
      \path (0.3,-0.5) rectangle (4.7,0.5);
      \shade[inner color=green,outer color=green!10] (\n,0) circle(.6);
      \foreach \i in {1,...,4} \fill[cyan] (\i,0) circle(.3);
    \end{tikzpicture}
  }
\end{animateinline}

%%%%%%%%%%%
% controls
%%%%%%%%%%%
\makebox[4cm]{%
\controlButton{\faPowerOff}{%
  if(anim.metronome.isPlaying) anim.metronome.stopFirst(); 
  else anim.metronome.playFwd();
}\hfill
% tempo
\controlButton{\faMinusCircle}{%
  try {--anim.tempo.frameNum;} catch (e) {}
}\,%
\begin{animateinline}[label=tempo,step,nomouse,poster=10,timeline=tempo.txt]{1}
  \multiframe{39}{i=0+1}{
    \pgfmathparse{\tempos[\i]}
    \makebox[\widthof{000}][c]{\strut\pgfmathresult}
  }
\end{animateinline}\,%
\controlButton{\faPlusCircle}{%
  try {++anim.tempo.frameNum;} catch (e) {}
}}
\end{center}
\end{document}

Independiente, animadoGIFes tonto y sordo, que yo sepa, y no parece existir un método de fácil acceso para sincronizar un Gif incrustado (en una página web) con un sonido. PeroSVGes muy superior, ya que es vectorial y por tanto libremente escalable.

Respuesta2

Alternativamente, puedes hacer la animación en otro lugar con sonido y agregarla a Beamer Files. Beamer parece tener un paquete multimedia. También movie15 parece prometedor.

Mira este hilo sobre Multimedia/sonido.Cómo incluir un archivo de audio en PDFQuizás ese sea un punto de partida válido.

información relacionada