moving ecasound
This commit is contained in:
parent
6c1e1b6b59
commit
eb2caf0adc
434 changed files with 26547 additions and 0 deletions
|
@ -0,0 +1,714 @@
|
|||
\documentclass{article}
|
||||
\usepackage[T1]{fontenc}
|
||||
\usepackage{ae}
|
||||
|
||||
%\usepackage{html}
|
||||
%\bodytext{link="#662a00" vlink="#666655" bgcolor="#ffffff"}
|
||||
|
||||
\title{Ecasound Control Interface Guide}
|
||||
\author{Kai Vehmanen, Brad Bowman, Tony Leake, Jan Weil, Mario Lang}
|
||||
\date{03062006}
|
||||
\begin{document}
|
||||
|
||||
\maketitle
|
||||
\tableofcontents
|
||||
\clearpage
|
||||
|
||||
% ----------------------------------------------------------------------
|
||||
% ----------------------------------------------------------------------
|
||||
\section{Introduction}
|
||||
The idea behind the Ecasound Control Interface (ECI) is to take a subset of
|
||||
functionality provided by libecasound, provide a simple API for it, and
|
||||
port it to various languages. At the moment, implementations of the
|
||||
ECI API are available for C, C++, elisp, Python and Ruby. These all
|
||||
come by default with the Ecasound package. Additional implementations,
|
||||
for example for Perl and PHP, are distributed independently.
|
||||
|
||||
ECI is heavily based on Ecasound's interactive mode (EIAM), and the
|
||||
services it provides. See \texttt{ecasound-iam(1) manual page} for
|
||||
a detailed EIAM documentation.
|
||||
|
||||
% ----------------------------------------------------------------------
|
||||
% ----------------------------------------------------------------------
|
||||
\section{Document history}
|
||||
\begin{itemize}
|
||||
\item 04.06.2006 - Added more information to the ``Tips for debugging'' section.
|
||||
\item 21.03.2005 - Updated the ``Tips for debugging'' section.
|
||||
\item 25.09.2004 - Updated the ``Return values'' section based on feedback
|
||||
from Adam Linson.
|
||||
\item 02.05.2004 - ``Emacs'' section added (written by Mario Lang).
|
||||
\item 28.11.2003 - ``Ruby'' section added (written by Jan Weil).
|
||||
Updated the introduction.
|
||||
\item 26.11.2003 - Fix filename for the alternative Python API (eci.py).
|
||||
\item 18.11.2003 - Typo fixes. Updated documentation to reflect the new
|
||||
naming convention (ecasound refers to the binary,
|
||||
Ecasound refers to the whole package).
|
||||
\item 26.10.2002 - Changed the C++ linking example.
|
||||
\item 24.10.2002 - Added ``Notes Concerning Standalone ECI Implementations''
|
||||
section. Added compilation examples.
|
||||
\item 06.10.2002 - Added ``Application development'' section.
|
||||
\item 05.10.2002 - Changed the libecasoundc link path.
|
||||
\item 29.09.2002 - ``PHP'' section added (written by Tony Leake).
|
||||
\item 25.04.2002 - Changed headers path from ``<ecasoundc/file.h>'' to
|
||||
``<file.h>'' and added library version number to
|
||||
link instructions.
|
||||
\item 21.10.2001 - Added this history section. Minor changes to
|
||||
ECI examples.
|
||||
\end{itemize}
|
||||
|
||||
% ----------------------------------------------------------------------
|
||||
% ----------------------------------------------------------------------
|
||||
\section{General}
|
||||
ECI doesn't provide any routines that directly manipulate audio or
|
||||
Ecasound objects. What it does provide is an easy and generic way
|
||||
to issue EIAM (Ecasound Inter-Active Mode) commands, access the
|
||||
command return-values and perform error handling.
|
||||
|
||||
This approach has two benefits. First, it is possible to keep the API
|
||||
small, and thus make it easier to port ECI to new languages. Secondly,
|
||||
it's possible to keep ECI relatively stable. Ecasound itself is a large,
|
||||
developing library. New features are added all the time, and from time
|
||||
to time, older parts of the library will get rewritten to better suit
|
||||
new uses. Now for application developers wanting to take advantage of
|
||||
libecasound, these constant changes are very annoying, especially if
|
||||
your specific app doesn't need the latest new features. In these
|
||||
cases, ECI is the best platform for application development.
|
||||
|
||||
|
||||
% ----------------------------------------------------------------------
|
||||
\subsection{What's it good for?}
|
||||
|
||||
Specific tasks ECI is aimed at:
|
||||
|
||||
\begin{itemize}
|
||||
\item 1. automating (scripting in its traditional sense)
|
||||
\item 2. frontends (generic / specialized)
|
||||
\item 3. sound services to other apps
|
||||
\end{itemize}
|
||||
|
||||
|
||||
% ----------------------------------------------------------------------
|
||||
\subsection{Services and behaviour}
|
||||
|
||||
Here is a list of services provided by all ECI implementations:
|
||||
|
||||
\subsubsection{Actions}
|
||||
\begin{description}
|
||||
\item[command(string)]
|
||||
Issue an EIAM command.
|
||||
|
||||
\item[command\_float\_arg(string, float)]
|
||||
Issue an EIAM command. This function can be used instead of
|
||||
\emph{command(string)}, if the command in question requires exactly one
|
||||
numerical parameter. This way it's possible to avoid the extra
|
||||
string -> float conversion, which would lead to lost precision.
|
||||
\end{description}
|
||||
|
||||
\subsubsection{Return values}
|
||||
Each EIAM command has exactly one return value type. After a command
|
||||
has been issued, only one last\_type() functions returns a non-empty
|
||||
value. For example, last\_float() only returns a valid value if
|
||||
\emph{last\_type() == 'f'} holds true. Not all EIAM commands return
|
||||
a value (return type is void).
|
||||
|
||||
\begin{description}
|
||||
\item[last\_string()]
|
||||
Returns the last string return value.
|
||||
|
||||
\item[last\_string\_list()]
|
||||
Returns the last collection of strings (one or more strings).
|
||||
|
||||
\item[last\_float()]
|
||||
Returns the last floating-point return value. Note! last\_float()
|
||||
doesn't refer to the C/C++ type 'float'. In most implementations,
|
||||
floats are 64bit values (doubles in C/C++).
|
||||
|
||||
\item[last\_integer()]
|
||||
Returns the last integer return value. This function is also
|
||||
used to return boolean values, where non-zero means 'true'
|
||||
and zero 'false'.
|
||||
|
||||
\item[last\_long\_integer()]
|
||||
Returns the last long integer return value. Long integers are
|
||||
used to pass values like 'length\_in\_samples' and 'length\_in\_bytes'.
|
||||
It's implementation specific whether there's any real difference
|
||||
between integers and long integers.
|
||||
\end{description}
|
||||
|
||||
\subsubsection{Errors}
|
||||
\begin{description}
|
||||
\item[error()]
|
||||
Returns true (!= 0) if error has occured during the execution
|
||||
of last EIAM command. Otherwise returns false (= 0).
|
||||
|
||||
\item[last\_error()]
|
||||
Returns a string describing the last error. If the last EIAM command
|
||||
was executed succesfully, last\_error() returns an empty string.
|
||||
|
||||
\end{description}
|
||||
|
||||
\subsubsection{Other}
|
||||
\begin{description}
|
||||
\item[initialize()]
|
||||
Reserve resources.
|
||||
|
||||
\item[cleanup()]
|
||||
Free all reserved resources.
|
||||
\end{description}
|
||||
|
||||
|
||||
|
||||
% ----------------------------------------------------------------------
|
||||
\subsection{Porting to new environments}
|
||||
Porting ECI to new languages should be easy. All there is to do is
|
||||
to implement the services listed in the previous section to the target
|
||||
language. In most cases it's to easiest to use the C++ or C ECI
|
||||
as the underlying implementation to build upon.
|
||||
|
||||
|
||||
|
||||
% ----------------------------------------------------------------------
|
||||
% ----------------------------------------------------------------------
|
||||
\section{Implementations}
|
||||
|
||||
|
||||
% ----------------------------------------------------------------------
|
||||
\subsection{General}
|
||||
|
||||
\subsubsection{Overview}
|
||||
This section contains overview of how ECI is implemented in the
|
||||
discussed language (eg. as a single class, set of classes, set of
|
||||
routines, etc).
|
||||
|
||||
\subsubsection{Usage}
|
||||
A quick tutorial to get you started.
|
||||
|
||||
\subsubsection{Example}
|
||||
Implementation of the following:
|
||||
\begin{enumerate}
|
||||
\item Setup ECI to read audio from file, apply a 100Hz lowpass filter, and
|
||||
send it to the soundcard (/dev/dsp).
|
||||
\item Every second, check the current position. If the stream has
|
||||
been running for over 15 seconds, exit immediately. Also,
|
||||
every second, increase the lowpass filter's cutoff frequency
|
||||
by 500Hz.
|
||||
\item Stop the stream (if not already finished) and disconnect the
|
||||
chainsetup. Print chain operator status info.
|
||||
\end{enumerate}
|
||||
|
||||
|
||||
% ----------------------------------------------------------------------
|
||||
\subsection{Notes Concerning Standalone ECI Implementations}
|
||||
|
||||
The C implementation of ECI is not directly linked against the main
|
||||
Ecasound libraries. Instead, the ecasound executable is launched
|
||||
on the background and command pipes are used to communicate with it.
|
||||
|
||||
The launched ecasound executable can be selected by using the
|
||||
\emph{ECASOUND} environment variable. If it is not defined,
|
||||
the C ECI implementation will try to launch ``ecasound'' (ie.
|
||||
has to be somewhere in PATH).
|
||||
|
||||
In addition to the C implementation, this also affects all
|
||||
ECI implementations that are based on the C version. Currently
|
||||
this includes at least the Perl, PHP and Python ECI modules.
|
||||
|
||||
% ----------------------------------------------------------------------
|
||||
\subsection{C++}
|
||||
\subsubsection{Overview}
|
||||
C++ implementation is based around the ECA\_CONTROL\_INTERFACE class.
|
||||
STL vector is used for representing collections of objects
|
||||
(last\_string\_list()).
|
||||
|
||||
\subsubsection{Usage}
|
||||
\begin{enumerate}
|
||||
\item \#include <eca-control-interface.h>
|
||||
\item create an instance of the ECA\_CONTROL\_INTERFACE class
|
||||
and use its member functions
|
||||
\item link you app agains libecasoundc (-lecasoundc)
|
||||
\item compilation example: \emph{c++ -o ecidoc\_example ecidoc\_example.cpp `libecasoundc-config --cflags --libs`}
|
||||
\end{enumerate}
|
||||
|
||||
\subsubsection{Example}
|
||||
\begin{verbatim}
|
||||
|
||||
#include <iostream>
|
||||
#include <unistd.h>
|
||||
#include <eca-control-interface.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
double cutoff_inc = 500.0;
|
||||
|
||||
ECA_CONTROL_INTERFACE e;
|
||||
e.command("cs-add play_chainsetup");
|
||||
e.command("c-add 1st_chain");
|
||||
e.command("ai-add some_file.wav");
|
||||
e.command("ao-add /dev/dsp");
|
||||
e.command("cop-add -efl:100");
|
||||
e.command("cop-select 1");
|
||||
e.command("copp-select 1");
|
||||
e.command("cs-connect");
|
||||
e.command("start");
|
||||
while(1) {
|
||||
sleep(1);
|
||||
e.command("engine-status");
|
||||
if (e.last_string() != "running") break;
|
||||
e.command("get-position");
|
||||
double curpos = e.last_float();
|
||||
if (curpos > 15.0) break;
|
||||
e.command("copp-get");
|
||||
double next_cutoff = cutoff_inc + e.last_float();
|
||||
e.command_float_arg("copp-set", next_cutoff);
|
||||
}
|
||||
|
||||
e.command("stop");
|
||||
e.command("cs-disconnect");
|
||||
e.command("cop-status");
|
||||
cerr << "Chain operator status: " << e.last_string() << endl;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
\end{verbatim}
|
||||
|
||||
% ----------------------------------------------------------------------
|
||||
\subsection{C}
|
||||
\subsubsection{Overview}
|
||||
All C ECI functions are prefixed with "eci\_". When returning string
|
||||
values, a const pointer to a null-terminated char array (const char*)
|
||||
is returned. It's important to keep in mind that these are "borrowed"
|
||||
references. If you need to later use the data, you must copy
|
||||
it to application's own buffers.
|
||||
|
||||
Returning a list of strings is implemented using two functions:
|
||||
\emph{eci\_last\_string\_list\_count()} returns the number of strings
|
||||
available, and \emph{eci\_last\_string\_list\_item(int n)} returns a
|
||||
pointer (const char*) to the string at index \emph{n}.
|
||||
|
||||
\emph{Note!} As of Ecasound 2.0.1, the C ECI implementation also
|
||||
provides reentrant access to the ECI API. These
|
||||
alternative routines are marked with '\_r' postfix.
|
||||
|
||||
\subsubsection{Usage}
|
||||
|
||||
\begin{enumerate}
|
||||
\item \#include <ecasoundc.h>
|
||||
\item use the eci\_* routines
|
||||
\item link your app against libecasoundc (-lecasoundc)
|
||||
\item compilation example: \emph{gcc -o ecidoc\_example ecidoc\_example.c `libecasoundc-config --cflags --libs`}
|
||||
\end{enumerate}
|
||||
|
||||
\subsubsection{Example}
|
||||
\begin{verbatim}
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <ecasoundc.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
double cutoff_inc = 500.0;
|
||||
|
||||
eci_init();
|
||||
eci_command("cs-add play_chainsetup");
|
||||
eci_command("c-add 1st_chain");
|
||||
eci_command("ai-add some_file.wav");
|
||||
eci_command("ao-add /dev/dsp");
|
||||
eci_command("cop-add -efl:100");
|
||||
eci_command("cop-select 1");
|
||||
eci_command("copp-select 1");
|
||||
eci_command("cs-connect");
|
||||
eci_command("start");
|
||||
|
||||
while(1) {
|
||||
double curpos, next_cutoff;
|
||||
|
||||
sleep(1);
|
||||
eci_command("engine-status");
|
||||
if (strcmp(eci_last_string(), "running") != 0) break;
|
||||
eci_command("get-position");
|
||||
curpos = eci_last_float();
|
||||
if (curpos > 15.0) break;
|
||||
eci_command("copp-get");
|
||||
next_cutoff = cutoff_inc + eci_last_float();
|
||||
eci_command_float_arg("copp-set", next_cutoff);
|
||||
}
|
||||
|
||||
eci_command("stop");
|
||||
eci_command("cs-disconnect");
|
||||
eci_command("cop-status");
|
||||
printf("Chain operator status: %s", eci_last_string());
|
||||
eci_cleanup();
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
\end{verbatim}
|
||||
|
||||
% ----------------------------------------------------------------------
|
||||
\subsection{Emacs}
|
||||
\subsubsection{Overview}
|
||||
The Ecasound package comes with an 'Ecasound' library for Emacs included.
|
||||
ecasound.el is a implementation of the ECI API for Emacs, as well
|
||||
as an interactive interface to Ecasound sessions implemented
|
||||
on top of that. Simply use "M-x ecasound RET" to fire up an
|
||||
interactive Ecasound session.
|
||||
|
||||
All Emacs Lisp ECI functions are prefixed with ``eci\-''.
|
||||
'ecasound.el' is implemented in a high level manner which means
|
||||
that you won't find most of the commands known from libecasoundc like
|
||||
last\_string, last\_float, etc.
|
||||
Instead of that every call to function "eci-command", which accepts all
|
||||
the well known IAM commands, returns ecasound's response in an appropriate type
|
||||
automatically.
|
||||
If an error occurs, e. g. there's a typo in a command or a file is not found,
|
||||
the function returns ``nil''. In all other cases, either an automatically
|
||||
converted Lisp value is returned, or ``t'' in the case where there was no
|
||||
particular value returned.
|
||||
|
||||
Additionally, most of the available IAM commands have their own Emacs Lisp
|
||||
function including documentation and possibly a parameter list. All these
|
||||
functions are interactive, so you can use them in ecasound-iam-mode simply
|
||||
by invoking them via M-x or by pressing an assigned key combination.
|
||||
Emacs will prompt you for the required parameters, providing completion
|
||||
wherever possible.
|
||||
|
||||
As a convention, "eci-command" and its variants do take a buffer or process
|
||||
as an optional last argument. If this is ``nil'', the current
|
||||
buffer is assumed to be the ecasound session refered to by this call.
|
||||
This makes it possible to use several ECI sessions concurrently, dispatching
|
||||
on the buffer or process in use.
|
||||
|
||||
\subsubsection{Usage}
|
||||
\begin{enumerate}
|
||||
\item make ecasound.el available in your ``load-path''
|
||||
\item (require 'ecasound)
|
||||
\item create a buffer with an associated Ecasound session (``eci-init'')
|
||||
\item use ``eci\-'' functions with the new buffer
|
||||
\end{enumerate}
|
||||
|
||||
\subsubsection{Example}
|
||||
\begin{verbatim}
|
||||
(require 'ecasound)
|
||||
|
||||
(defun example (file &optional cutoff-increment session)
|
||||
(unless cutoff-increment (setq cutoff-increment 500.0))
|
||||
(with-current-buffer (or session (eci-init))
|
||||
(eci-cs-add "play_chainsetup")
|
||||
(eci-c-add "1st_chain")
|
||||
(eci-ai-add file)
|
||||
(eci-ao-add "/dev/dsp")
|
||||
(eci-cop-add "-efl:100")
|
||||
(eci-cop-select 1)
|
||||
(eci-copp-select 1)
|
||||
(eci-cs-connect)
|
||||
(eci-start)
|
||||
(sit-for 1)
|
||||
(while (and (string= (eci-engine-status) "running")
|
||||
(<= (eci-get-position) 15))
|
||||
(eci-copp-set (+ cutoff-increment (eci-copp-get)))
|
||||
(sit-for 1))
|
||||
(eci-command "stop")
|
||||
(when (eci-cs-disconnect)
|
||||
(destructuring-bind
|
||||
((cop n1 (copp n2 val)))
|
||||
(cdr (assoc "1st_chain" (eci-cop-status)))
|
||||
(message "%s %s is now %f" cop copp val)))))
|
||||
\end{verbatim}
|
||||
|
||||
NOTE: function ``eci-cop-status'' is actually a very high level function
|
||||
which already converts the returned information to a nested list
|
||||
structure.
|
||||
|
||||
For more complex examples of the Emacs Lisp ECI implementation, see function
|
||||
``eci-example'', ``ecasound-normalize'' and ``ecasound-signalview'' in
|
||||
ecasound.el.
|
||||
|
||||
% ----------------------------------------------------------------------
|
||||
\subsection{Python}
|
||||
\subsubsection{Overview}
|
||||
Python implementation is based around the ECA\_CONTROL\_INTERFACE class.
|
||||
Lists are used for representing collections of objects.
|
||||
|
||||
Note! Eric S. Tiedemann has written an alternative Python interface
|
||||
to ECI. You'll find this interface included in the main
|
||||
Ecasound packege, in ``pyecasound/eci.py''. To use this instead
|
||||
of the standard interface, just 'import eci' and you're set! :)
|
||||
|
||||
\subsubsection{Usage}
|
||||
|
||||
\begin{enumerate}
|
||||
\item import pyeca
|
||||
\item create an instance of the ECA\_CONTROL\_INTERFACE class
|
||||
and use its member functions
|
||||
\item python 'yourapp.py' and that's it :)
|
||||
\end{enumerate}
|
||||
|
||||
\subsubsection{Example}
|
||||
\begin{verbatim}
|
||||
|
||||
#!/usr/local/bin/python
|
||||
import time
|
||||
from pyeca import *
|
||||
e = ECA_CONTROL_INTERFACE()
|
||||
e.command("cs-add play_chainsetup")
|
||||
e.command("c-add 1st_chain")
|
||||
e.command("ai-add some_file.wav")
|
||||
e.command("ao-add /dev/dsp")
|
||||
e.command("cop-add -efl:100")
|
||||
e.command("cop-select 1")
|
||||
e.command("copp-select 1")
|
||||
e.command("cs-connect")
|
||||
e.command("start")
|
||||
cutoff_inc = 500.0
|
||||
while 1:
|
||||
time.sleep(1)
|
||||
e.command("engine-status")
|
||||
if e.last_string() != "running": break
|
||||
e.command("get-position")
|
||||
curpos = e.last_float()
|
||||
if curpos > 15: break
|
||||
e.command("copp-get")
|
||||
next_cutoff = cutoff_inc + e.last_float()
|
||||
e.command_float_arg("copp-set", next_cutoff)
|
||||
e.command("stop")
|
||||
e.command("cs-disconnect")
|
||||
e.command("cop-status")
|
||||
print "Chain operator status: ", e.last_string()
|
||||
|
||||
\end{verbatim}
|
||||
|
||||
% ----------------------------------------------------------------------
|
||||
\subsection{Perl}
|
||||
\subsubsection{Overview}
|
||||
Audio::Ecasound provides perl bindings to the Ecasound
|
||||
control interface of the Ecasound program. You can use
|
||||
perl to automate or interact with Ecasound so you don't
|
||||
have to turn you back on the adoring masses packed into
|
||||
Wembly Stadium.
|
||||
|
||||
Audio::Ecasound was written by Brad Bowman. At the moment this module
|
||||
is not distributed with Ecasound. To get the latest version, check the
|
||||
following \texttt{CPAN link}.
|
||||
|
||||
\subsubsection{Usage}
|
||||
See the below example. For more info, here's another
|
||||
\texttt{CPAN link}.
|
||||
|
||||
\subsubsection{Example}
|
||||
use Audio::Ecasound qw(:simple);
|
||||
|
||||
\begin{verbatim}
|
||||
|
||||
eci("cs-add play_chainsetup");
|
||||
eci("c-add 1st_chain");
|
||||
eci("ai-add some_file.wav");
|
||||
eci("ao-add /dev/dsp");
|
||||
# multiple \n separated commands
|
||||
eci("cop-add -efl:100
|
||||
# with comments
|
||||
cop-select 1
|
||||
copp-select 1
|
||||
cs-connect");
|
||||
eci("start");
|
||||
my $cutoff_inc = 500.0;
|
||||
while (1) {
|
||||
sleep(1);
|
||||
last if eci("engine-status") ne "running";
|
||||
my $curpos = eci("get-position");
|
||||
last if $curpos > 15;
|
||||
my $next_cutoff = $cutoff_inc + eci("copp-get");
|
||||
# Optional float argument
|
||||
eci("copp-set", $next_cutoff);
|
||||
}
|
||||
eci("stop");
|
||||
eci("cs-disconnect");
|
||||
print "Chain operator status: ", eci("cop-status");
|
||||
|
||||
\end{verbatim}
|
||||
|
||||
% ----------------------------------------------------------------------
|
||||
\subsection{PHP}
|
||||
\subsubsection{Overview}
|
||||
This PHP extension provides bindings to the Ecasound
|
||||
control interface. It is useful both for scripting Ecasound
|
||||
and for writing graphical audio applications with PHP Gtk.
|
||||
|
||||
The PHP Ecasound extension was written by Tony Leake. At the moment this module
|
||||
is not distributed with Ecasound. The latest version and example scripts, are
|
||||
available from \texttt{http://www.webwise-data.co.uk/php\_audio/php\_audio\_extension.html}.
|
||||
|
||||
\subsubsection{Usage}
|
||||
\begin{enumerate}
|
||||
\item Obtain and build the Ecasound PHP extension
|
||||
\item Initialise Ecasound, eci\_int();
|
||||
\item Issue EAM commands eg, eci\_command("cs-add my\_chain\_setup");
|
||||
\item Free resources, eci\_cleanup();
|
||||
\end{enumerate}
|
||||
|
||||
\subsubsection{Example}
|
||||
\begin{verbatim}
|
||||
|
||||
Implementation of the following:
|
||||
|
||||
1. Setup ECI to read audio from file, apply a 100Hz lowpass filter,
|
||||
and send it to the soundcard (/dev/dsp).
|
||||
2. Every second, check the current position. If the stream has been
|
||||
running for over 15 seconds, exit immediately. Also, every second,
|
||||
increase the lowpass filter's cutoff frequency by 500Hz.
|
||||
3. Stop the stream (if not already finished) and disconnect the chainsetup.
|
||||
Print chain operator status info
|
||||
|
||||
<?php
|
||||
|
||||
$cutoff_inc = 500.0;
|
||||
$curpos=0;
|
||||
$next_cutoff=0;
|
||||
|
||||
eci_init();
|
||||
eci_command("cs-add play_chainsetup");
|
||||
eci_command("c-add 1st_chain");
|
||||
eci_command("ai-add /tmp/somefile.wav");
|
||||
eci_command("ao-add /dev/dsp");
|
||||
eci_command("cop-add -efl:10");
|
||||
eci_command("cop-select 1");
|
||||
eci_command("copp-select 1");
|
||||
eci_command("cs-connect");
|
||||
eci_command("start");
|
||||
|
||||
while(1) {
|
||||
|
||||
sleep(1);
|
||||
|
||||
eci_command("engine-status");
|
||||
if (eci_last_string() !="running"){
|
||||
break;
|
||||
}
|
||||
|
||||
eci_command("get-position");
|
||||
$curpos = eci_last_float();
|
||||
if ($curpos > 15.0){
|
||||
break;
|
||||
}
|
||||
|
||||
eci_command("copp-get");
|
||||
$next_cutoff = $cutoff_inc + eci_last_float();
|
||||
eci_command_float_arg("copp-set",$next_cutoff);
|
||||
}
|
||||
|
||||
eci_command("stop");
|
||||
eci_command("cs-disconnect");
|
||||
eci_command("cop-status");
|
||||
|
||||
printf("Chain operator status: %s", eci_last_string());
|
||||
|
||||
eci_cleanup();
|
||||
?>
|
||||
\end{verbatim}
|
||||
|
||||
% ----------------------------------------------------------------------
|
||||
\subsection{Ruby}
|
||||
\subsubsection{Overview}
|
||||
The Ecasound package comes with an 'Ecasound' module for Ruby included.
|
||||
If ruby is detected during the installation process it is installed
|
||||
automatically (assuming you are installing ecasound from source code).
|
||||
The module contains the class definition of a native ecasound control interface
|
||||
called "ControlInterface".
|
||||
|
||||
'Ecasound::ControlInterface' is implemented in a high level manner which means
|
||||
that you won't find most of the commands known from libecasoundc like
|
||||
last\_string, last\_float, etc.
|
||||
Instead of that every call to the instance method "command", which accepts all
|
||||
the well known IAM commands, returns ecasound's response in an appropriate type
|
||||
automatically.
|
||||
If an error occurs, e. g. there's a typo in a command or a file is not found,
|
||||
an exception of type EcasoundError is raised.
|
||||
|
||||
\subsubsection{Usage}
|
||||
\begin{enumerate}
|
||||
\item require 'ecasound'
|
||||
\item create an instance of Ecasound::ControlInterface
|
||||
\item use it's command method to send IAM commands to ecasound
|
||||
\item catch an EcasoundError if necessary
|
||||
\end{enumerate}
|
||||
|
||||
\subsubsection{Example}
|
||||
\begin{verbatim}
|
||||
#!/usr/bin/env ruby
|
||||
require "ecasound"
|
||||
|
||||
SOME_FILE = "path/to/file.wav"
|
||||
|
||||
e = Ecasound::ControlInterface.new()
|
||||
e.command("cs-add play_chainsetup")
|
||||
e.command("c-add 1st_chain")
|
||||
e.command("ai-add #{SOME_FILE}")
|
||||
e.command("ao-add /dev/dsp")
|
||||
e.command("cop-add -efl:100")
|
||||
e.command("cop-select 1")
|
||||
e.command("copp-select 1")
|
||||
e.command("cs-connect")
|
||||
e.command("start")
|
||||
|
||||
cutoff_inc = 500.0
|
||||
|
||||
loop do
|
||||
sleep(1)
|
||||
break if e.command("engine-status") != "running"
|
||||
break if e.command("get-position") > 15
|
||||
e.command("copp-set #{cutoff_inc + e.command('copp-get')}")
|
||||
end
|
||||
|
||||
e.command("stop")
|
||||
e.command("cs-disconnect")
|
||||
|
||||
$stdout << "Chain operator status: " + e.command("cop-status") + "\n"
|
||||
\end{verbatim}
|
||||
|
||||
% ----------------------------------------------------------------------
|
||||
% ----------------------------------------------------------------------
|
||||
\section{Application development}
|
||||
|
||||
% ----------------------------------------------------------------------
|
||||
\subsection{Tips for debugging}
|
||||
|
||||
Here's a few tips what to do if the ECI app you have developed
|
||||
is not working correctly.
|
||||
|
||||
\begin{enumerate}
|
||||
\item Check your Ecasound installation. Try to run the ``ecasound''
|
||||
console user-interface and verify that the basic functionality
|
||||
is working (ie. something like ``ecasound -i foo.wav -o
|
||||
/dev/dsp''.
|
||||
|
||||
\item If developing in C or C++, check that your application
|
||||
is correcly linked: ``ldd /path/to/myapp''. All the libraries
|
||||
should be properly found.
|
||||
|
||||
\item Check error conditions. You should remember to check
|
||||
for errors in your ECI apps using the eci\_error() and
|
||||
eci\_last\_error() functions. Especially when intializing
|
||||
ECI for the first time and after important commands
|
||||
like ``cs-connect'', you should always check for errors.
|
||||
|
||||
\item Use the ECASOUND\_LOGFILE environment variable to write all
|
||||
engine output to a separate logfile. See ecasound(1) manpage
|
||||
for details on how to use this mechanism. Requires Ecasound
|
||||
version 2.4.5 or newer.
|
||||
|
||||
\item Utilize the ``int-log-history'' ECI command added to
|
||||
version 2.4.0 of Ecasound. Recent messages from the
|
||||
engine can help to track down the problem. Before use, you
|
||||
need to first set the history length to a non-zero value with
|
||||
``int-set-log-history-length''.
|
||||
|
||||
\item Launch Ecasound in interactive mode (``ecasound -c''),
|
||||
and issue the commands your ECI application is using,
|
||||
manually one-by-one and see what happens. If something
|
||||
goes wrong, increase Ecasound's debug level (for instance
|
||||
``-ddd'') and re-run the test.
|
||||
|
||||
\end{enumerate}
|
||||
|
||||
\end{document}
|
Loading…
Add table
Add a link
Reference in a new issue