353 lines
10 KiB
C++
353 lines
10 KiB
C++
#ifndef INCLUDED_AUDIOIO_H
|
|
#define INCLUDED_AUDIOIO_H
|
|
|
|
#include <string>
|
|
|
|
#include "eca-audio-position.h"
|
|
#include "eca-audio-time.h"
|
|
#include "eca-audio-format.h"
|
|
#include "dynamic-object.h"
|
|
|
|
class SAMPLE_BUFFER;
|
|
class AUDIO_IO_MANAGER;
|
|
|
|
using std::string;
|
|
|
|
/**
|
|
* Virtual base class for all audio I/O objects. Different types
|
|
* of audio objects include files, audio devices, sound
|
|
* producing program modules, audio server clients, and so on.
|
|
*
|
|
* The class interface is divided into following sections:
|
|
*
|
|
* - type definitions
|
|
*
|
|
* - attributes
|
|
*
|
|
* - configuration (setting and getting configuration parameters)
|
|
*
|
|
* - functionality (control and runtime information)
|
|
*
|
|
* - runtime information
|
|
*
|
|
* - constructors and destructors
|
|
*
|
|
* @author Kai Vehmanen
|
|
*/
|
|
class AUDIO_IO : public DYNAMIC_OBJECT<string>,
|
|
public ECA_AUDIO_FORMAT,
|
|
public ECA_AUDIO_POSITION {
|
|
|
|
public:
|
|
|
|
/** @name Public type definitions and constants */
|
|
/*@{*/
|
|
|
|
/**
|
|
* Input/Output mode
|
|
*
|
|
* @see io_mode()
|
|
*
|
|
* io_read
|
|
*
|
|
* Device is opened for input. If opening a file,
|
|
* it must exist.
|
|
*
|
|
* io_write
|
|
*
|
|
* Device is opened for output. If opening a file and
|
|
* and output exists, it is first truncated.
|
|
*
|
|
* io_readwrite
|
|
*
|
|
* Device is opened for both reading and writing. If
|
|
* opening a file, a new file is created if needed.
|
|
* When switching from read to write or vica versa,
|
|
* position should be reset before using the device.
|
|
**/
|
|
enum Io_mode { io_read = 1, io_write = 2, io_readwrite = 4 };
|
|
|
|
class SETUP_ERROR {
|
|
public:
|
|
enum Error_type {
|
|
sample_format, /* unsupported sample format */
|
|
channels, /* unsupported channel count */
|
|
sample_rate, /* unsupported sample_rate */
|
|
interleaving, /* non-interleaved or interleaved channel organization not supported */
|
|
io_mode, /* unsupported I/O mode */
|
|
buffersize, /* unsupported buffersize */
|
|
blockmode, /* non-blocking or blocking mode not supported */
|
|
dynamic_params, /* invalid dynamic parameters (for instance invalid label()) */
|
|
unexpected /* unexpected/unknown error */
|
|
};
|
|
|
|
const string& message(void) const;
|
|
Error_type type(void) const;
|
|
SETUP_ERROR(Error_type type, const string& message);
|
|
|
|
private:
|
|
Error_type type_rep;
|
|
string message_rep;
|
|
};
|
|
|
|
public:
|
|
|
|
/*@}*/
|
|
|
|
/** @name Public functions for handling object managers */
|
|
/*@{*/
|
|
|
|
/**
|
|
* Creates an object manager for this audio object type.
|
|
*
|
|
* @return 0 if no manager objects are not supported
|
|
*/
|
|
virtual AUDIO_IO_MANAGER* create_object_manager(void) const { return(0); }
|
|
|
|
/*@}*/
|
|
|
|
/** @name Constructors and destructors */
|
|
/*@{*/
|
|
|
|
virtual AUDIO_IO* clone(void) const = 0;
|
|
virtual AUDIO_IO* new_expr(void) const = 0;
|
|
virtual ~AUDIO_IO(void);
|
|
AUDIO_IO(const string& name = "uninitialized",
|
|
int mode = io_read);
|
|
|
|
/*@}*/
|
|
|
|
/** @name Attribute functions */
|
|
/*@{*/
|
|
|
|
virtual int supported_io_modes(void) const;
|
|
virtual bool supports_nonblocking_mode(void) const;
|
|
virtual bool finite_length_stream(void) const;
|
|
virtual bool locked_audio_format(void) const;
|
|
|
|
/*@}*/
|
|
|
|
/** @name Configuration
|
|
*
|
|
* For setting and getting configuration parameters.
|
|
*/
|
|
/*@{*/
|
|
|
|
/**
|
|
* Sets the sample buffer size in sample frames.
|
|
*
|
|
* When reading data with read_buffer(), buffersize()
|
|
* determines how many sample frames of data is
|
|
* processed per call.
|
|
*
|
|
* Otherwise buffersize() is only used for initializing
|
|
* devices and data structures.
|
|
*
|
|
* Device should always be able to write all sample
|
|
* data passed to write_buffer(), independently from current
|
|
* buffersize() value.
|
|
*
|
|
* @see buffersize()
|
|
*/
|
|
virtual void set_buffersize(long int samples) = 0;
|
|
|
|
/**
|
|
* Returns the current buffersize in sample frames.
|
|
*
|
|
* @see set_buffersize()
|
|
*/
|
|
virtual long int buffersize(void) const = 0;
|
|
|
|
int io_mode(void) const;
|
|
const string& label(void) const;
|
|
string format_info(void) const;
|
|
|
|
void set_io_mode(int mode);
|
|
void set_label(const string& id_label);
|
|
void toggle_nonblocking_mode(bool value);
|
|
|
|
virtual string parameter_names(void) const { return("label"); }
|
|
virtual void set_parameter(int param, string value);
|
|
virtual string get_parameter(int param) const;
|
|
|
|
public:
|
|
|
|
/*@}*/
|
|
|
|
/** @name Main functionality */
|
|
/*@{*/
|
|
|
|
/**
|
|
* Reads samples and store them to buffer pointed by 'sbuf'. If
|
|
* necessary, the target buffer will be resized (both length
|
|
* and number of channels).
|
|
*
|
|
* The sample buffer event tags may also be set during
|
|
* this method call (see SAMPLE_BUFFER documentation for more
|
|
* details).
|
|
*
|
|
* It's important to note that SAMPLE_BUFFER audio format cannot be
|
|
* changed during processing. This means that audio data must be converted
|
|
* from audio object's internal format to that of 'sbuf' given as
|
|
* argument. SAMPLE_BUFFER class provides tools for all normal conversion
|
|
* operations. If you need direct access to object's data, a lower
|
|
* abstraction level should be used (@see AUDIO_IO_BUFFERED).
|
|
*
|
|
* Note! The implementations should call set_position_in_samples()
|
|
* or change_position_in_samples() in ECA_AUDIO_POSITION.
|
|
*
|
|
* @pre io_mode() == io_read || io_mode() == io_readwrite
|
|
* @pre readable() == true
|
|
* @pre sbuf != 0
|
|
* @post sbuf->length_in_samples() <= buffersize()
|
|
* @post sbuf->number_of_channels() == channels()
|
|
*/
|
|
virtual void read_buffer(SAMPLE_BUFFER* sbuf) = 0;
|
|
|
|
/**
|
|
* Writes all data from sample buffer pointed by 'sbuf' to
|
|
* this object. Notes concerning read_buffer() also apply to
|
|
* this routine.
|
|
*
|
|
* Note! The implementations should call set_position_in_samples()
|
|
* or change_position_in_samples() in ECA_AUDIO_POSITION.
|
|
*
|
|
* @pre io_mode() == io_write || io_mode() == io_readwrite
|
|
* @pre writable() == true
|
|
* @pre sbuf != 0
|
|
*/
|
|
virtual void write_buffer(SAMPLE_BUFFER* sbuf) = 0;
|
|
|
|
/**
|
|
* Opens the audio object (possibly in exclusive mode).
|
|
* This routine is used for initializing external connections
|
|
* (opening files or devices, loading shared libraries,
|
|
* opening IPC connections). As it's impossible to know in
|
|
* advance what might happen, open() may throw an
|
|
* exception. This way it becomes possible to provide
|
|
* more verbose information about the problem that caused
|
|
* open() to fail.
|
|
*
|
|
* At this point the various audio parameters are used
|
|
* for the first time. Unless locked_audio_format() is 'true',
|
|
* object tries to use the audio format parameters set prior to
|
|
* this call. If object doesn't support the given parameter
|
|
* combination, it can either try adjust them to closest
|
|
* matching, or in the worst case, throw an SETUP_ERROR
|
|
* exception (see above).
|
|
*
|
|
* @pre is_open() != true
|
|
* @post readable() == true || writable() == true || is_open() != true
|
|
*/
|
|
virtual void open(void) throw (AUDIO_IO::SETUP_ERROR &);
|
|
|
|
/**
|
|
* Closes audio object. After calling this routine,
|
|
* all resources (for instance files and devices) must
|
|
* be freed so that they can be used by other processes.
|
|
*
|
|
* @pre is_open() == true
|
|
* @post readable() != true
|
|
* @post writable() != true
|
|
*/
|
|
virtual void close(void);
|
|
|
|
/*@}*/
|
|
|
|
/** @name Runtime information */
|
|
/*@{*/
|
|
|
|
/**
|
|
* Returns a file descriptor id suitable for poll() and
|
|
* select() system calls. If polling is not supported,
|
|
* returns value of '-1'.
|
|
*/
|
|
virtual int poll_descriptor(void) const { return(-1); }
|
|
|
|
/**
|
|
* If 'supports_nonblocking_mode() == true', this function returns
|
|
* the number of samples frames that is available for reading, or
|
|
* alternatively, how many sample frames can be written without
|
|
* blocking. This function can be used for implementing nonblocking
|
|
* input and output with devices supporting it.
|
|
*
|
|
* Note, you should use set_buffersize() for setting how
|
|
* many sample frames read_buffer() will ask from the device.
|
|
*
|
|
* require:
|
|
* supports_nonblocking_mode() == true
|
|
*/
|
|
virtual long int samples_available(void) const { return(0); }
|
|
|
|
/**
|
|
* Has device been opened (with open())?
|
|
*/
|
|
bool is_open(void) const { return(open_rep); }
|
|
|
|
/**
|
|
* Whether all data has been processed? If opened in mode 'io_read',
|
|
* this means that end of stream has been reached. If opened in
|
|
* 'io_write' or 'io_readwrite' modes, finished status usually
|
|
* means that an error has occured (no space left, etc). After
|
|
* finished() has returned 'true', further calls to read_buffer()
|
|
* and/or write_buffer() won't process any data.
|
|
*
|
|
* For output for which 'finite_length_stream()' is true, when
|
|
* 'finished()' returns true, that means an error has occured.
|
|
* Otherwise 'finished()' just tells that further attempts to do
|
|
* i/o will fail.
|
|
*/
|
|
virtual bool finished(void) const = 0;
|
|
|
|
virtual bool nonblocking_mode(void) const;
|
|
virtual bool readable(void) const;
|
|
virtual bool writable(void) const;
|
|
virtual string status(void) const;
|
|
|
|
ECA_AUDIO_TIME length(void) const;
|
|
ECA_AUDIO_TIME position(void) const;
|
|
|
|
/*@}*/
|
|
|
|
/** @name Functions overridden and reimplemented from
|
|
* ECA_AUDIO_POSITION and ECA_AUDIO_FORMAT */
|
|
/*@{*/
|
|
|
|
SAMPLE_SPECS::sample_rate_t samples_per_second(void) const;
|
|
virtual void set_samples_per_second(SAMPLE_SPECS::sample_rate_t v);
|
|
virtual void set_audio_format(const ECA_AUDIO_FORMAT& f_str);
|
|
|
|
/*@}*/
|
|
|
|
/** @name Functions implemented from ECA_AUDIO_POSITION */
|
|
/*@{*/
|
|
|
|
virtual bool supports_seeking(void) const;
|
|
virtual bool supports_seeking_sample_accurate(void) const;
|
|
virtual SAMPLE_SPECS::sample_pos_t seek_position(SAMPLE_SPECS::sample_pos_t pos);
|
|
|
|
/*@}*/
|
|
|
|
protected:
|
|
|
|
/** @name Functions provided for subclasses. */
|
|
/*@{*/
|
|
|
|
void position(const ECA_AUDIO_TIME& v);
|
|
void length(const ECA_AUDIO_TIME& v);
|
|
|
|
std::string parameter_get_to_string(int param) const;
|
|
std::string parameter_set_to_string(int param, std::string value) const;
|
|
|
|
/*@{*/
|
|
|
|
private:
|
|
|
|
int io_mode_rep;
|
|
string id_label_rep;
|
|
bool nonblocking_rep;
|
|
bool open_rep;
|
|
};
|
|
|
|
#endif
|