mirror of
https://github.com/larsimmisch/pyalsaaudio.git
synced 2026-06-01 19:07:02 +00:00
- Added close methods to PCM and Mixer
- Avoid internal re-opening of PCM objects when parameters change. - PCM objects can be opened by card id - Mixer objects can be openend by card index (this is not consistent, but ALSA works this way) - Adjusted and cleaned up documentation. git-svn-id: svn://svn.code.sf.net/p/pyalsaaudio/code/trunk@26 ec2f30ec-7544-0410-870e-f70ca00c83f0
This commit is contained in:
+367
-64
@@ -16,7 +16,8 @@
|
||||
#include "Python.h"
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
#include "stringobject.h"
|
||||
#define PyUnicode_FromString PyString_FromString
|
||||
#define PyUnicode_AS_DATA PyString_AS_STRING
|
||||
#define PyUnicode_Check PyString_Check
|
||||
#endif
|
||||
#include <alsa/asoundlib.h>
|
||||
#include <stdio.h>
|
||||
@@ -71,14 +72,98 @@ typedef struct {
|
||||
|
||||
} alsamixer_t;
|
||||
|
||||
static PyObject *ALSAAudioError;
|
||||
/* Translate a card id to a ALSA cardname
|
||||
|
||||
Returns a newly allocated string.
|
||||
*/
|
||||
char *translate_cardname(char *name)
|
||||
{
|
||||
static char dflt[] = "default";
|
||||
char *full = NULL;
|
||||
|
||||
if (!name || !strcmp(name, dflt))
|
||||
return strdup(dflt);
|
||||
|
||||
// If we find a colon, we assume it is a real ALSA cardname
|
||||
if (strchr(name, ':'))
|
||||
return strdup(name);
|
||||
|
||||
full = malloc(strlen("default:CARD=") + strlen(name) + 1);
|
||||
sprintf(full, "default:CARD=%s", name);
|
||||
|
||||
return full;
|
||||
}
|
||||
|
||||
/* Translate a card index to a ALSA cardname
|
||||
|
||||
Returns a newly allocated string.
|
||||
*/
|
||||
char *translate_cardidx(int idx)
|
||||
{
|
||||
char name[32];
|
||||
|
||||
sprintf(name, "hw:%d", idx);
|
||||
|
||||
return strdup(name);
|
||||
}
|
||||
|
||||
/******************************************/
|
||||
/* PCM object wrapper */
|
||||
/******************************************/
|
||||
|
||||
static PyTypeObject ALSAPCMType;
|
||||
static PyObject *ALSAAudioError;
|
||||
|
||||
static PyObject *
|
||||
alsacard_list(PyObject *self, PyObject *args) {
|
||||
int rc;
|
||||
int card = -1;
|
||||
snd_ctl_card_info_t *info;
|
||||
snd_ctl_t *handle;
|
||||
PyObject *result = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args,":cards"))
|
||||
return NULL;
|
||||
|
||||
snd_ctl_card_info_alloca(&info);
|
||||
result = PyList_New(0);
|
||||
|
||||
for (rc = snd_card_next(&card); !rc && (card >= 0);
|
||||
rc = snd_card_next(&card))
|
||||
{
|
||||
char name[32];
|
||||
int err;
|
||||
|
||||
/* One would be tempted to think that snd_card_get_name returns a name
|
||||
that is actually meaningful for any further operations.
|
||||
|
||||
Not in ALSA land. Here we need the id, not the name */
|
||||
|
||||
sprintf(name, "hw:%d", card);
|
||||
if ((err = snd_ctl_open(&handle, name, 0)) < 0) {
|
||||
PyErr_SetString(ALSAAudioError,snd_strerror(err));
|
||||
return NULL;
|
||||
}
|
||||
if ((err = snd_ctl_card_info(handle, info)) < 0) {
|
||||
PyErr_SetString(ALSAAudioError,snd_strerror(err));
|
||||
snd_ctl_close(handle);
|
||||
Py_DECREF(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyList_Append(result,
|
||||
PyUnicode_FromString(snd_ctl_card_info_get_id(info)));
|
||||
|
||||
snd_ctl_close(handle);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(cards_doc,
|
||||
"cards()\n\
|
||||
\n\
|
||||
List the available card ids.");
|
||||
|
||||
static int alsapcm_setup(alsapcm_t *self) {
|
||||
int res,dir;
|
||||
@@ -87,18 +172,12 @@ static int alsapcm_setup(alsapcm_t *self) {
|
||||
snd_pcm_uframes_t frames;
|
||||
snd_pcm_hw_params_t *hwparams;
|
||||
|
||||
if (self->handle) {
|
||||
snd_pcm_close(self->handle);
|
||||
self->handle = 0;
|
||||
}
|
||||
res = snd_pcm_open(&(self->handle),self->cardname,self->pcmtype,
|
||||
self->pcmmode);
|
||||
if (res < 0) return res;
|
||||
|
||||
/* Allocate a hwparam structure, and fill it in with configuration space */
|
||||
/* Allocate a hwparam structure on the stack,
|
||||
and fill it in with configuration space */
|
||||
snd_pcm_hw_params_alloca(&hwparams);
|
||||
res = snd_pcm_hw_params_any(self->handle, hwparams);
|
||||
if (res < 0) return res;
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
/* Fill it in with default values. */
|
||||
snd_pcm_hw_params_any(self->handle, hwparams);
|
||||
@@ -110,7 +189,7 @@ static int alsapcm_setup(alsapcm_t *self) {
|
||||
snd_pcm_hw_params_set_rate(self->handle, hwparams, self->rate, dir);
|
||||
snd_pcm_hw_params_set_period_size(self->handle, hwparams, self->periodsize,
|
||||
dir);
|
||||
snd_pcm_hw_params_set_periods(self->handle,hwparams,4,0);
|
||||
snd_pcm_hw_params_set_periods(self->handle, hwparams, 4, 0);
|
||||
|
||||
/* Write it to the device */
|
||||
res = snd_pcm_hw_params(self->handle, hwparams);
|
||||
@@ -118,15 +197,16 @@ static int alsapcm_setup(alsapcm_t *self) {
|
||||
|
||||
/* Query current settings. These may differ from the requested values,
|
||||
which should therefore be sync'ed with actual values */
|
||||
snd_pcm_hw_params_current(self->handle,hwparams);
|
||||
snd_pcm_hw_params_current(self->handle, hwparams);
|
||||
|
||||
snd_pcm_hw_params_get_format(hwparams,&fmt); self->format = fmt;
|
||||
snd_pcm_hw_params_get_channels(hwparams,&val); self->channels = val;
|
||||
snd_pcm_hw_params_get_rate(hwparams,&val,&dir); self->rate = val;
|
||||
snd_pcm_hw_params_get_period_size(hwparams,&frames,&dir);
|
||||
snd_pcm_hw_params_get_format(hwparams, &fmt); self->format = fmt;
|
||||
snd_pcm_hw_params_get_channels(hwparams, &val); self->channels = val;
|
||||
snd_pcm_hw_params_get_rate(hwparams, &val, &dir); self->rate = val;
|
||||
snd_pcm_hw_params_get_period_size(hwparams, &frames, &dir);
|
||||
self->periodsize = (int) frames;
|
||||
|
||||
self->framesize = self->channels * snd_pcm_hw_params_get_sbits(hwparams)/8;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -134,11 +214,15 @@ static PyObject *
|
||||
alsapcm_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
|
||||
int res;
|
||||
alsapcm_t *self;
|
||||
int pcmtype=0;
|
||||
int pcmmode=0;
|
||||
char *cardname = "default";
|
||||
if (!PyArg_ParseTuple(args,"|iis",&pcmtype,&pcmmode,&cardname))
|
||||
int pcmtype = SND_PCM_STREAM_PLAYBACK;
|
||||
int pcmmode = 0;
|
||||
char *kw[] = { "type", "mode", "card", NULL };
|
||||
char *cardname = NULL;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|iiz", kw,
|
||||
&pcmtype, &pcmmode, &cardname))
|
||||
return NULL;
|
||||
|
||||
if (!(self = (alsapcm_t *)PyObject_New(alsapcm_t, &ALSAPCMType)))
|
||||
return NULL;
|
||||
|
||||
@@ -152,17 +236,20 @@ alsapcm_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
|
||||
PyErr_SetString(ALSAAudioError, "Invalid PCM mode");
|
||||
return NULL;
|
||||
}
|
||||
self->handle = 0;
|
||||
self->pcmtype = pcmtype;
|
||||
self->pcmmode = pcmmode;
|
||||
self->cardname = strdup(cardname);
|
||||
|
||||
self->cardname = translate_cardname(cardname);
|
||||
self->channels = 2;
|
||||
self->rate = 44100;
|
||||
self->format = SND_PCM_FORMAT_S16_LE;
|
||||
self->periodsize = 32;
|
||||
|
||||
self->handle = 0;
|
||||
res = alsapcm_setup(self);
|
||||
res = snd_pcm_open(&(self->handle), self->cardname, self->pcmtype,
|
||||
self->pcmmode);
|
||||
|
||||
if (res >= 0)
|
||||
res = alsapcm_setup(self);
|
||||
|
||||
if (res < 0) {
|
||||
if (self->handle) {
|
||||
@@ -175,7 +262,8 @@ alsapcm_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
|
||||
return (PyObject *)self;
|
||||
}
|
||||
|
||||
static void alsapcm_dealloc(alsapcm_t *self) {
|
||||
static void alsapcm_dealloc(alsapcm_t *self)
|
||||
{
|
||||
if (self->handle) {
|
||||
snd_pcm_drain(self->handle);
|
||||
snd_pcm_close(self->handle);
|
||||
@@ -184,6 +272,30 @@ static void alsapcm_dealloc(alsapcm_t *self) {
|
||||
PyObject_Del(self);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
alsapcm_close(alsapcm_t *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args,":close"))
|
||||
return NULL;
|
||||
|
||||
if (self->handle) {
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
snd_pcm_drain(self->handle);
|
||||
snd_pcm_close(self->handle);
|
||||
Py_END_ALLOW_THREADS
|
||||
|
||||
self->handle = 0;
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(pcm_close_doc,
|
||||
"close() -> None\n\
|
||||
\n\
|
||||
Close a PCM device.");
|
||||
|
||||
static PyObject *
|
||||
alsapcm_dumpinfo(alsapcm_t *self, PyObject *args) {
|
||||
unsigned int val,val2;
|
||||
@@ -194,8 +306,13 @@ alsapcm_dumpinfo(alsapcm_t *self, PyObject *args) {
|
||||
snd_pcm_hw_params_alloca(&hwparams);
|
||||
snd_pcm_hw_params_current(self->handle,hwparams);
|
||||
|
||||
if (!PyArg_ParseTuple(args,":dumpinfo"))
|
||||
return NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args,":dumpinfo")) return NULL;
|
||||
if (!self->handle) {
|
||||
PyErr_SetString(ALSAAudioError, "PCM device is closed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
printf("PCM handle name = '%s'\n", snd_pcm_name(self->handle));
|
||||
printf("PCM state = %s\n", snd_pcm_state_name(snd_pcm_state(self->handle)));
|
||||
@@ -280,7 +397,14 @@ alsapcm_dumpinfo(alsapcm_t *self, PyObject *args) {
|
||||
|
||||
static PyObject *
|
||||
alsapcm_pcmtype(alsapcm_t *self, PyObject *args) {
|
||||
if (!PyArg_ParseTuple(args,":pcmtype")) return NULL;
|
||||
if (!PyArg_ParseTuple(args,":pcmtype"))
|
||||
return NULL;
|
||||
|
||||
if (!self->handle) {
|
||||
PyErr_SetString(ALSAAudioError, "PCM device is closed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return PyLong_FromLong(self->pcmtype);
|
||||
}
|
||||
|
||||
@@ -292,7 +416,14 @@ Returns either PCM_CAPTURE or PCM_PLAYBACK.");
|
||||
|
||||
static PyObject *
|
||||
alsapcm_pcmmode(alsapcm_t *self, PyObject *args) {
|
||||
if (!PyArg_ParseTuple(args,"pcmmode")) return NULL;
|
||||
if (!PyArg_ParseTuple(args,":pcmmode"))
|
||||
return NULL;
|
||||
|
||||
if (!self->handle) {
|
||||
PyErr_SetString(ALSAAudioError, "PCM device is closed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return PyLong_FromLong(self->pcmmode);
|
||||
}
|
||||
|
||||
@@ -307,7 +438,14 @@ Returns the mode of the PCM object. One of:\n\
|
||||
|
||||
static PyObject *
|
||||
alsapcm_cardname(alsapcm_t *self, PyObject *args) {
|
||||
if (!PyArg_ParseTuple(args,":cardname")) return NULL;
|
||||
if (!PyArg_ParseTuple(args,":cardname"))
|
||||
return NULL;
|
||||
|
||||
if (!self->handle) {
|
||||
PyErr_SetString(ALSAAudioError, "PCM device is closed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return PyUnicode_FromString(self->cardname);
|
||||
}
|
||||
|
||||
@@ -321,7 +459,14 @@ static PyObject *
|
||||
alsapcm_setchannels(alsapcm_t *self, PyObject *args) {
|
||||
int channels;
|
||||
int res;
|
||||
if (!PyArg_ParseTuple(args,"i:setchannels",&channels)) return NULL;
|
||||
if (!PyArg_ParseTuple(args,"i:setchannels",&channels))
|
||||
return NULL;
|
||||
|
||||
if (!self->handle) {
|
||||
PyErr_SetString(ALSAAudioError, "PCM device is closed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->channels = channels;
|
||||
res = alsapcm_setup(self);
|
||||
if (res < 0) {
|
||||
@@ -344,7 +489,14 @@ static PyObject *
|
||||
alsapcm_setrate(alsapcm_t *self, PyObject *args) {
|
||||
int rate;
|
||||
int res;
|
||||
if (!PyArg_ParseTuple(args,"i:setrate",&rate)) return NULL;
|
||||
if (!PyArg_ParseTuple(args,"i:setrate",&rate))
|
||||
return NULL;
|
||||
|
||||
if (!self->handle) {
|
||||
PyErr_SetString(ALSAAudioError, "PCM device is closed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->rate = rate;
|
||||
res = alsapcm_setup(self);
|
||||
if (res < 0) {
|
||||
@@ -358,14 +510,21 @@ PyDoc_STRVAR(setrate_doc,
|
||||
"setrate(rate)\n\
|
||||
\n\
|
||||
Set the sample rate in Hz for the device. Typical values are\n\
|
||||
8000(telephony), 11025, 44100 (CD), 48000 (DVD audio) and 96000");
|
||||
8000 (telephony), 11025, 44100 (CD), 48000 (DVD audio) and 96000");
|
||||
|
||||
|
||||
static PyObject *
|
||||
alsapcm_setformat(alsapcm_t *self, PyObject *args) {
|
||||
int format;
|
||||
int res;
|
||||
if (!PyArg_ParseTuple(args,"i:setformat",&format)) return NULL;
|
||||
if (!PyArg_ParseTuple(args,"i:setformat",&format))
|
||||
return NULL;
|
||||
|
||||
if (!self->handle) {
|
||||
PyErr_SetString(ALSAAudioError, "PCM device is closed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->format = format;
|
||||
res = alsapcm_setup(self);
|
||||
if (res < 0) {
|
||||
@@ -383,7 +542,14 @@ static PyObject *
|
||||
alsapcm_setperiodsize(alsapcm_t *self, PyObject *args) {
|
||||
int periodsize;
|
||||
int res;
|
||||
if (!PyArg_ParseTuple(args,"i:setperiodsize",&periodsize)) return NULL;
|
||||
if (!PyArg_ParseTuple(args,"i:setperiodsize",&periodsize))
|
||||
return NULL;
|
||||
|
||||
if (!self->handle) {
|
||||
PyErr_SetString(ALSAAudioError, "PCM device is closed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->periodsize = periodsize;
|
||||
res = alsapcm_setup(self);
|
||||
if (res < 0) {
|
||||
@@ -394,12 +560,12 @@ alsapcm_setperiodsize(alsapcm_t *self, PyObject *args) {
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(setperiodsize_doc,
|
||||
"setperiodsize(period)\n\
|
||||
"setperiodsize(period) -> int\n\
|
||||
\n\
|
||||
Sets the actual period size in frames. Each write should consist of\n\
|
||||
exactly this number of frames, and each read will return this number of\n\
|
||||
frames (unless the device is in PCM_NONBLOCK mode, in which case it\n\
|
||||
may return nothing at all)");
|
||||
may return nothing at all).");
|
||||
|
||||
static PyObject *
|
||||
alsapcm_read(alsapcm_t *self, PyObject *args) {
|
||||
@@ -412,7 +578,14 @@ alsapcm_read(alsapcm_t *self, PyObject *args) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!PyArg_ParseTuple(args,":read")) return NULL;
|
||||
if (!PyArg_ParseTuple(args,":read"))
|
||||
return NULL;
|
||||
|
||||
if (!self->handle) {
|
||||
PyErr_SetString(ALSAAudioError, "PCM device is closed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (self->pcmtype != SND_PCM_STREAM_CAPTURE) {
|
||||
PyErr_SetString(ALSAAudioError,"Cannot read from playback PCM");
|
||||
return NULL;
|
||||
@@ -476,6 +649,11 @@ static PyObject *alsapcm_write(alsapcm_t *self, PyObject *args) {
|
||||
datalen = buf.len;
|
||||
#endif
|
||||
|
||||
if (!self->handle) {
|
||||
PyErr_SetString(ALSAAudioError, "PCM device is closed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (datalen % self->framesize) {
|
||||
PyErr_SetString(ALSAAudioError,
|
||||
"Data size must be a multiple of framesize");
|
||||
@@ -522,7 +700,14 @@ written at a later time.");
|
||||
|
||||
static PyObject *alsapcm_pause(alsapcm_t *self, PyObject *args) {
|
||||
int enabled=1, res;
|
||||
if (!PyArg_ParseTuple(args,"|i:pause",&enabled)) return NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args,"|i:pause",&enabled))
|
||||
return NULL;
|
||||
|
||||
if (!self->handle) {
|
||||
PyErr_SetString(ALSAAudioError, "PCM device is closed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
res = snd_pcm_pause(self->handle, enabled);
|
||||
@@ -558,6 +743,7 @@ static PyMethodDef alsapcm_methods[] = {
|
||||
{"read", (PyCFunction)alsapcm_read, METH_VARARGS, read_doc},
|
||||
{"write", (PyCFunction)alsapcm_write, METH_VARARGS, write_doc},
|
||||
{"pause", (PyCFunction)alsapcm_pause, METH_VARARGS, pause_doc},
|
||||
{"close", (PyCFunction)alsapcm_close, METH_VARARGS, pcm_close_doc},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -655,18 +841,25 @@ alsamixer_list(PyObject *self, PyObject *args) {
|
||||
snd_mixer_selem_id_t *sid;
|
||||
snd_mixer_elem_t *elem;
|
||||
int err;
|
||||
char *cardname = "default";
|
||||
PyObject *result = PyList_New(0);
|
||||
int cardidx = 0;
|
||||
char cardname[32];
|
||||
PyObject *result;
|
||||
|
||||
if (!PyArg_ParseTuple(args,"|s:mixers",&cardname)) return NULL;
|
||||
if (!PyArg_ParseTuple(args,"|i:mixers",&cardidx))
|
||||
return NULL;
|
||||
|
||||
sprintf(cardname, "hw:%d", cardidx);
|
||||
|
||||
snd_mixer_selem_id_alloca(&sid);
|
||||
err = alsamixer_gethandle(cardname,&handle);
|
||||
err = alsamixer_gethandle(cardname, &handle);
|
||||
if (err < 0) {
|
||||
PyErr_SetString(ALSAAudioError,snd_strerror(err));
|
||||
snd_mixer_close(handle);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = PyList_New(0);
|
||||
|
||||
for (elem = snd_mixer_first_elem(handle); elem;
|
||||
elem = snd_mixer_elem_next(elem))
|
||||
{
|
||||
@@ -703,23 +896,30 @@ static PyObject *
|
||||
alsamixer_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
|
||||
alsamixer_t *self;
|
||||
int err;
|
||||
char *cardname = "default";
|
||||
int cardindex = 0;
|
||||
char *control = "Master";
|
||||
int id = 0;
|
||||
snd_mixer_elem_t *elem;
|
||||
int channel;
|
||||
|
||||
if (!PyArg_ParseTuple(args,"|sis",&control,&id,&cardname))
|
||||
char *kw[] = { "control", "id", "cardindex", NULL };
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|sii", kw,
|
||||
&control, &id, &cardindex))
|
||||
return NULL;
|
||||
|
||||
if (!(self = (alsamixer_t *)PyObject_New(alsamixer_t, &ALSAMixerType)))
|
||||
return NULL;
|
||||
|
||||
err = alsamixer_gethandle(cardname,&self->handle);
|
||||
self->handle = 0;
|
||||
self->cardname = translate_cardidx(cardindex);
|
||||
|
||||
err = alsamixer_gethandle(self->cardname, &self->handle);
|
||||
if (err<0) {
|
||||
PyErr_SetString(ALSAAudioError,snd_strerror(err));
|
||||
free(self->cardname);
|
||||
return NULL;
|
||||
}
|
||||
self->cardname = strdup(cardname);
|
||||
}
|
||||
|
||||
self->controlname = strdup(control);
|
||||
self->controlid = id;
|
||||
|
||||
@@ -811,8 +1011,37 @@ static void alsamixer_dealloc(alsamixer_t *self) {
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
alsamixer_cardname(alsamixer_t *self, PyObject *args) {
|
||||
if (!PyArg_ParseTuple(args,":cardname")) return NULL;
|
||||
alsamixer_close(alsamixer_t *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args,":close"))
|
||||
return NULL;
|
||||
|
||||
snd_mixer_close(self->handle);
|
||||
free(self->cardname);
|
||||
free(self->controlname);
|
||||
self->handle = 0;
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(mixer_close_doc,
|
||||
"close() -> None\n\
|
||||
\n\
|
||||
Close a Mixer.");
|
||||
|
||||
static PyObject *
|
||||
alsamixer_cardname(alsamixer_t *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args,":cardname"))
|
||||
return NULL;
|
||||
|
||||
if (!self->handle)
|
||||
{
|
||||
PyErr_SetString(ALSAAudioError, "Mixer is closed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return PyUnicode_FromString(self->cardname);
|
||||
}
|
||||
|
||||
@@ -821,10 +1050,18 @@ PyDoc_STRVAR(mixer_cardname_doc,
|
||||
\n\
|
||||
Returns the name of the sound card used by this Mixer object.");
|
||||
|
||||
|
||||
static PyObject *
|
||||
alsamixer_mixer(alsamixer_t *self, PyObject *args) {
|
||||
if (!PyArg_ParseTuple(args,":mixer")) return NULL;
|
||||
alsamixer_mixer(alsamixer_t *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args,":mixer"))
|
||||
return NULL;
|
||||
|
||||
if (!self->handle)
|
||||
{
|
||||
PyErr_SetString(ALSAAudioError, "Mixer is closed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return PyUnicode_FromString(self->controlname);
|
||||
}
|
||||
|
||||
@@ -837,7 +1074,15 @@ for example 'Master' or 'PCM'");
|
||||
|
||||
static PyObject *
|
||||
alsamixer_mixerid(alsamixer_t *self, PyObject *args) {
|
||||
if (!PyArg_ParseTuple(args,":mixerid")) return NULL;
|
||||
if (!PyArg_ParseTuple(args,":mixerid"))
|
||||
return NULL;
|
||||
|
||||
if (!self->handle)
|
||||
{
|
||||
PyErr_SetString(ALSAAudioError, "Mixer is closed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return PyLong_FromLong(self->controlid);
|
||||
}
|
||||
|
||||
@@ -948,7 +1193,14 @@ alsamixer_getvolume(alsamixer_t *self, PyObject *args) {
|
||||
char *dirstr = 0;
|
||||
PyObject *result;
|
||||
|
||||
if (!PyArg_ParseTuple(args,"|s:getvolume",&dirstr)) return NULL;
|
||||
if (!PyArg_ParseTuple(args,"|s:getvolume",&dirstr))
|
||||
return NULL;
|
||||
|
||||
if (!self->handle)
|
||||
{
|
||||
PyErr_SetString(ALSAAudioError, "Mixer is closed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
elem = alsamixer_find_elem(self->handle,self->controlname,self->controlid);
|
||||
|
||||
@@ -977,7 +1229,7 @@ alsamixer_getvolume(alsamixer_t *self, PyObject *args) {
|
||||
snd_mixer_selem_get_capture_volume(elem, channel, &ival);
|
||||
PyList_Append(
|
||||
result, PyLong_FromLong(alsamixer_getpercentage(self->cmin,
|
||||
self->cmax, ival)));
|
||||
self->cmax, ival)));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -1001,7 +1253,14 @@ alsamixer_getrange(alsamixer_t *self, PyObject *args) {
|
||||
int direction;
|
||||
char *dirstr = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args,"|s:getrange",&dirstr)) return NULL;
|
||||
if (!PyArg_ParseTuple(args,"|s:getrange",&dirstr))
|
||||
return NULL;
|
||||
|
||||
if (!self->handle)
|
||||
{
|
||||
PyErr_SetString(ALSAAudioError, "Mixer is closed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
elem = alsamixer_find_elem(self->handle,self->controlname,self->controlid);
|
||||
|
||||
@@ -1059,7 +1318,14 @@ alsamixer_getenum(alsamixer_t *self, PyObject *args) {
|
||||
char name[32];
|
||||
|
||||
PyObject *result;
|
||||
if (!PyArg_ParseTuple(args, ":getenum")) return NULL;
|
||||
if (!PyArg_ParseTuple(args, ":getenum"))
|
||||
return NULL;
|
||||
|
||||
if (!self->handle)
|
||||
{
|
||||
PyErr_SetString(ALSAAudioError, "Mixer is closed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
elem = alsamixer_find_elem(self->handle,self->controlname,self->controlid);
|
||||
if (!snd_mixer_selem_is_enumerated(elem)) {
|
||||
@@ -1127,7 +1393,14 @@ alsamixer_getmute(alsamixer_t *self, PyObject *args) {
|
||||
int i;
|
||||
int ival;
|
||||
PyObject *result;
|
||||
if (!PyArg_ParseTuple(args,":getmute")) return NULL;
|
||||
if (!PyArg_ParseTuple(args,":getmute"))
|
||||
return NULL;
|
||||
|
||||
if (!self->handle)
|
||||
{
|
||||
PyErr_SetString(ALSAAudioError, "Mixer is closed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
elem = alsamixer_find_elem(self->handle,self->controlname,self->controlid);
|
||||
if (!snd_mixer_selem_has_playback_switch(elem)) {
|
||||
@@ -1159,7 +1432,14 @@ alsamixer_getrec(alsamixer_t *self, PyObject *args) {
|
||||
int i;
|
||||
int ival;
|
||||
PyObject *result;
|
||||
if (!PyArg_ParseTuple(args,":getrec")) return NULL;
|
||||
if (!PyArg_ParseTuple(args,":getrec"))
|
||||
return NULL;
|
||||
|
||||
if (!self->handle)
|
||||
{
|
||||
PyErr_SetString(ALSAAudioError, "Mixer is closed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
elem = alsamixer_find_elem(self->handle,self->controlname,self->controlid);
|
||||
if (!snd_mixer_selem_has_capture_switch(elem)) {
|
||||
@@ -1202,6 +1482,12 @@ alsamixer_setvolume(alsamixer_t *self, PyObject *args) {
|
||||
PyErr_SetString(ALSAAudioError,"Volume must be between 0 and 100");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!self->handle)
|
||||
{
|
||||
PyErr_SetString(ALSAAudioError, "Mixer is closed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
elem = alsamixer_find_elem(self->handle,self->controlname,self->controlid);
|
||||
|
||||
@@ -1263,7 +1549,14 @@ alsamixer_setmute(alsamixer_t *self, PyObject *args) {
|
||||
int mute = 0;
|
||||
int done = 0;
|
||||
int channel = MIXER_CHANNEL_ALL;
|
||||
if (!PyArg_ParseTuple(args,"i|i:setmute",&mute,&channel)) return NULL;
|
||||
if (!PyArg_ParseTuple(args,"i|i:setmute",&mute,&channel))
|
||||
return NULL;
|
||||
|
||||
if (!self->handle)
|
||||
{
|
||||
PyErr_SetString(ALSAAudioError, "Mixer is closed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
elem = alsamixer_find_elem(self->handle,self->controlname,self->controlid);
|
||||
if (!snd_mixer_selem_has_playback_switch(elem)) {
|
||||
@@ -1304,7 +1597,15 @@ alsamixer_setrec(alsamixer_t *self, PyObject *args) {
|
||||
int rec = 0;
|
||||
int done = 0;
|
||||
int channel = MIXER_CHANNEL_ALL;
|
||||
if (!PyArg_ParseTuple(args,"i|i:setrec",&rec,&channel)) return NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args,"i|i:setrec",&rec,&channel))
|
||||
return NULL;
|
||||
|
||||
if (!self->handle)
|
||||
{
|
||||
PyErr_SetString(ALSAAudioError, "Mixer is closed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
elem = alsamixer_find_elem(self->handle,self->controlname,self->controlid);
|
||||
if (!snd_mixer_selem_has_capture_switch(elem)) {
|
||||
@@ -1341,6 +1642,7 @@ This method will fail if the mixer has no capture switch capabilities");
|
||||
static PyMethodDef alsamixer_methods[] = {
|
||||
{"cardname", (PyCFunction)alsamixer_cardname, METH_VARARGS,
|
||||
mixer_cardname_doc},
|
||||
{"close", (PyCFunction)alsamixer_close, METH_VARARGS, mixer_close_doc},
|
||||
{"mixer", (PyCFunction)alsamixer_mixer, METH_VARARGS, mixer_doc},
|
||||
{"mixerid", (PyCFunction)alsamixer_mixerid, METH_VARARGS, mixerid_doc},
|
||||
{"switchcap", (PyCFunction)alsamixer_switchcap, METH_VARARGS, switchcap_doc},
|
||||
@@ -1415,6 +1717,7 @@ static PyTypeObject ALSAMixerType = {
|
||||
/******************************************/
|
||||
|
||||
static PyMethodDef alsaaudio_methods[] = {
|
||||
{ "cards", alsacard_list, METH_VARARGS, cards_doc},
|
||||
{ "mixers", alsamixer_list, METH_VARARGS, mixers_doc},
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
+20
-20
@@ -9,7 +9,7 @@ PAPER =
|
||||
# Internal variables.
|
||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||
PAPEROPT_letter = -D latex_paper_size=letter
|
||||
ALLSPHINXOPTS = -d .build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||
ALLSPHINXOPTS = -d doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||
|
||||
SFUSER = larsimmisch
|
||||
|
||||
@@ -27,51 +27,51 @@ help:
|
||||
@echo " linkcheck to check all external links for integrity"
|
||||
|
||||
clean:
|
||||
-rm -rf .build/*
|
||||
-rm -rf html doctrees pickle htmlhelp latex changes linkcheck
|
||||
|
||||
html:
|
||||
mkdir -p .build/html .build/doctrees
|
||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) .build/html
|
||||
mkdir -p html doctrees
|
||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) html
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in .build/html."
|
||||
@echo "Build finished. The HTML pages are in html."
|
||||
|
||||
pickle:
|
||||
mkdir -p .build/pickle .build/doctrees
|
||||
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) .build/pickle
|
||||
mkdir -p pickle doctrees
|
||||
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) pickle
|
||||
@echo
|
||||
@echo "Build finished; now you can process the pickle files or run"
|
||||
@echo " sphinx-web .build/pickle"
|
||||
@echo " sphinx-web pickle"
|
||||
@echo "to start the sphinx-web server."
|
||||
|
||||
web: pickle
|
||||
|
||||
htmlhelp:
|
||||
mkdir -p .build/htmlhelp .build/doctrees
|
||||
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) .build/htmlhelp
|
||||
mkdir -p htmlhelp doctrees
|
||||
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) htmlhelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
||||
".hhp project file in .build/htmlhelp."
|
||||
".hhp project file in htmlhelp."
|
||||
|
||||
latex:
|
||||
mkdir -p .build/latex .build/doctrees
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) .build/latex
|
||||
mkdir -p latex doctrees
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) latex
|
||||
@echo
|
||||
@echo "Build finished; the LaTeX files are in .build/latex."
|
||||
@echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
|
||||
"run these through (pdf)latex."
|
||||
|
||||
changes:
|
||||
mkdir -p .build/changes .build/doctrees
|
||||
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) .build/changes
|
||||
mkdir -p changes doctrees
|
||||
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) changes
|
||||
@echo
|
||||
@echo "The overview file is in .build/changes."
|
||||
@echo "The overview file is in changes."
|
||||
|
||||
linkcheck:
|
||||
mkdir -p .build/linkcheck .build/doctrees
|
||||
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) .build/linkcheck
|
||||
mkdir -p linkcheck doctrees
|
||||
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) linkcheck
|
||||
@echo
|
||||
@echo "Link check complete; look for any errors in the above output " \
|
||||
"or in .build/linkcheck/output.txt."
|
||||
"or in linkcheck/output.txt."
|
||||
|
||||
install:
|
||||
scp -r .build/html/* $(SFUSER),pyalsaaudio@web.sourceforge.net:htdocs
|
||||
scp -r ./html/* $(SFUSER),pyalsaaudio@web.sourceforge.net:htdocs
|
||||
|
||||
+179
@@ -0,0 +1,179 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# alsaaudio documentation build configuration file, created by
|
||||
# sphinx-quickstart on Sat Nov 22 00:17:09 2008.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its containing dir.
|
||||
#
|
||||
# The contents of this file are pickled, so don't put values in the namespace
|
||||
# that aren't pickleable (module imports are okay, they're removed automatically).
|
||||
#
|
||||
# All configuration values have a default value; values that are commented out
|
||||
# serve to show the default value.
|
||||
|
||||
import sys, os
|
||||
|
||||
# If your extensions are in another directory, add it here. If the directory
|
||||
# is relative to the documentation root, use os.path.abspath to make it
|
||||
# absolute, like shown here.
|
||||
#sys.path.append(os.path.abspath('some/directory'))
|
||||
|
||||
# General configuration
|
||||
# ---------------------
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be extensions
|
||||
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||
extensions = []
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['.templates']
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.rst'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# General substitutions.
|
||||
project = u'alsaaudio'
|
||||
copyright = u'2008, Casper Wilstrup, Lars Immisch'
|
||||
|
||||
# The default replacements for |version| and |release|, also used in various
|
||||
# other places throughout the built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '0.4'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '0.4'
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
#today = ''
|
||||
# Else, today_fmt is used as the format for a strftime call.
|
||||
today_fmt = '%B %d, %Y'
|
||||
|
||||
# List of documents that shouldn't be included in the build.
|
||||
#unused_docs = []
|
||||
|
||||
# List of directories, relative to source directories, that shouldn't be searched
|
||||
# for source files.
|
||||
exclude_trees = ['.build']
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all documents.
|
||||
#default_role = None
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
#add_function_parentheses = True
|
||||
|
||||
# If true, the current module name will be prepended to all description
|
||||
# unit titles (such as .. function::).
|
||||
#add_module_names = True
|
||||
|
||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||
# output. They are ignored by default.
|
||||
#show_authors = False
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
|
||||
# Options for HTML output
|
||||
# -----------------------
|
||||
|
||||
# The style sheet to use for HTML and HTML Help pages. A file of that name
|
||||
# must exist either in Sphinx' static/ path, or in one of the custom paths
|
||||
# given in html_static_path.
|
||||
html_style = 'default.css'
|
||||
|
||||
# The name for this set of Sphinx documents. If None, it defaults to
|
||||
# "<project> v<release> documentation".
|
||||
#html_title = None
|
||||
|
||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||
#html_short_title = None
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top
|
||||
# of the sidebar.
|
||||
#html_logo = None
|
||||
|
||||
# The name of an image file (within the static path) to use as favicon of the
|
||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
# pixels large.
|
||||
#html_favicon = None
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['static']
|
||||
|
||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||
# using the given strftime format.
|
||||
html_last_updated_fmt = '%b %d, %Y'
|
||||
|
||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||
# typographically correct entities.
|
||||
#html_use_smartypants = True
|
||||
|
||||
# Custom sidebar templates, maps document names to template names.
|
||||
#html_sidebars = {}
|
||||
|
||||
# Additional templates that should be rendered to pages, maps page names to
|
||||
# template names.
|
||||
#html_additional_pages = {}
|
||||
|
||||
# If false, no module index is generated.
|
||||
#html_use_modindex = True
|
||||
|
||||
# If false, no index is generated.
|
||||
#html_use_index = True
|
||||
|
||||
# If true, the index is split into individual pages for each letter.
|
||||
#html_split_index = False
|
||||
|
||||
# If true, the reST sources are included in the HTML build as _sources/<name>.
|
||||
#html_copy_source = True
|
||||
|
||||
# If true, an OpenSearch description file will be output, and all pages will
|
||||
# contain a <link> tag referring to it. The value of this option must be the
|
||||
# base URL from which the finished HTML is served.
|
||||
#html_use_opensearch = ''
|
||||
|
||||
# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
|
||||
#html_file_suffix = ''
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'alsaaudiodoc'
|
||||
|
||||
|
||||
# Options for LaTeX output
|
||||
# ------------------------
|
||||
|
||||
# The paper size ('letter' or 'a4').
|
||||
#latex_paper_size = 'letter'
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#latex_font_size = '10pt'
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author, document class [howto/manual]).
|
||||
latex_documents = [
|
||||
('index', 'alsaaudio.tex', u'alsaaudio Documentation',
|
||||
u'Casper Wilstrup, Lars Immisch', 'manual'),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
# the title page.
|
||||
#latex_logo = None
|
||||
|
||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||
# not chapters.
|
||||
#latex_use_parts = False
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#latex_preamble = ''
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#latex_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#latex_use_modindex = True
|
||||
@@ -5,6 +5,7 @@ alsaaudio documentation
|
||||
:maxdepth: 2
|
||||
|
||||
pyalsaaudio
|
||||
terminology
|
||||
libalsaaudio
|
||||
|
||||
|
||||
|
||||
+97
-133
@@ -1,84 +1,6 @@
|
||||
****************************
|
||||
PCM Terminology and Concepts
|
||||
****************************
|
||||
|
||||
In order to use PCM devices it is useful to be familiar with some concepts and
|
||||
terminology.
|
||||
|
||||
Sample
|
||||
PCM audio, whether it is input or output, consists of *samples*.
|
||||
A single sample represents the amplitude of one channel of sound
|
||||
at a certain point in time. A lot of individual samples are
|
||||
necessary to represent actual sound; for CD audio, 44100 samples
|
||||
are taken every second.
|
||||
|
||||
Samples can be of many different sizes, ranging from 8 bit to 64
|
||||
bit precision. The specific format of each sample can also vary -
|
||||
they can be big endian byte integers, little endian byte integers, or
|
||||
floating point numbers.
|
||||
|
||||
Musically, the sample size determines the dynamic range. The
|
||||
dynamic range is the difference between the quietest and the
|
||||
loudest signal that can be resproduced.
|
||||
|
||||
Frame
|
||||
A frame consists of exactly one sample per channel. If there is only one
|
||||
channel (Mono sound) a frame is simply a single sample. If the sound is
|
||||
stereo, each frame consists of two samples, etc.
|
||||
|
||||
Frame size
|
||||
This is the size in bytes of each frame. This can vary a lot: if each sample
|
||||
is 8 bits, and we're handling mono sound, the frame size is one byte.
|
||||
Similarly in 6 channel audio with 64 bit floating point samples, the frame
|
||||
size is 48 bytes
|
||||
|
||||
Rate
|
||||
PCM sound consists of a flow of sound frames. The sound rate controls how
|
||||
often the current frame is replaced. For example, a rate of 8000 Hz
|
||||
means that a new frame is played or captured 8000 times per second.
|
||||
|
||||
Data rate
|
||||
This is the number of bytes, which must be recorded or provided per
|
||||
second at a certain frame size and rate.
|
||||
|
||||
8000 Hz mono sound with 8 bit (1 byte) samples has a data rate of
|
||||
8000 \* 1 \* 1 = 8 kb/s or 64kbit/s. This is typically used for telephony.
|
||||
|
||||
At the other end of the scale, 96000 Hz, 6 channel sound with 64
|
||||
bit (8 bytes) samples has a data rate of 96000 \* 6 \* 8 = 4608
|
||||
kb/s (almost 5 Mb sound data per second)
|
||||
|
||||
Period
|
||||
When the hardware processes data this is done in chunks of frames. The time
|
||||
interval between each processing (A/D or D/A conversion) is known
|
||||
as the period.
|
||||
The size of the period has direct implication on the latency of the
|
||||
sound input or output. For low-latency the period size should be
|
||||
very small, while low CPU resource usage would usually demand
|
||||
larger period sizes. With ALSA, the CPU utilization is not impacted
|
||||
much by the period size, since the kernel layer buffers multiple
|
||||
periods internally, so each period generates an interrupt and a
|
||||
memory copy, but userspace can be slower and read or write multiple
|
||||
periods at the same time.
|
||||
|
||||
Period size
|
||||
This is the size of each period in Hz. *Not bytes, but Hz!.* In
|
||||
:mod:`alsaaudio` the period size is set directly, and it is
|
||||
therefore important to understand the significance of this
|
||||
number. If the period size is configured to for example 32,
|
||||
each write should contain exactly 32 frames of sound data, and each
|
||||
read will return either 32 frames of data or nothing at all.
|
||||
|
||||
Once you understand these concepts, you will be ready to use the PCM API. Read
|
||||
on.
|
||||
|
||||
|
||||
********************
|
||||
Module documentation
|
||||
********************
|
||||
|
||||
****************
|
||||
:mod:`alsaaudio`
|
||||
================
|
||||
****************
|
||||
|
||||
.. module:: alsaaudio
|
||||
:platform: Linux
|
||||
@@ -112,75 +34,67 @@ The :mod:`alsaaudio` module defines functions and classes for using ALSA.
|
||||
.. % should be enclosed in \var{...}.
|
||||
|
||||
|
||||
.. function:: mixers([cardname])
|
||||
.. function:: cards()
|
||||
|
||||
List the available mixers. The optional *cardname* specifies which card
|
||||
should be queried (this is only relevant if you have more than one sound
|
||||
card). Omit to use the default sound card.
|
||||
List the available cards.
|
||||
|
||||
.. function:: mixers([cardindex])
|
||||
|
||||
.. class:: PCM([type], [mode], [cardname])
|
||||
List the available mixers. The optional *cardindex* specifies which card
|
||||
should be queried. The default is 0.
|
||||
|
||||
This class is used to represent a PCM device (both playback and capture
|
||||
devices). The arguments are: --- *type* - can be either PCM_CAPTURE or
|
||||
PCM_PLAYBACK (default). --- *mode* - can be either PCM_NONBLOCK,
|
||||
PCM_ASYNC, or PCM_NORMAL (the default). --- *cardname* - specifies
|
||||
which card should be used (this is only relevant if you have more
|
||||
than one sound card). Omit to use the default sound card
|
||||
.. class:: PCM(type=PCM_PLAYBACK, mode=PCM_NORMAL, card='default')
|
||||
|
||||
This class is used to represent a PCM device (both for playback and
|
||||
recording - capture). The arguments are:
|
||||
|
||||
.. class:: Mixer([control], [id], [cardname])
|
||||
* *type* - can be either ``PCM_CAPTURE`` or ``PCM_PLAYBACK`` (default).
|
||||
* *mode* - can be either ``PCM_NONBLOCK``, or ``PCM_NORMAL`` (default).
|
||||
* *card* - specifies the name of the card that should be used.
|
||||
|
||||
This class is used to access a specific ALSA mixer. The arguments are: ---
|
||||
*control* - Name of the chosen mixed (default is Master). --- *id* - id of
|
||||
mixer (default is 0) -- More explanation needed here --- *cardname*
|
||||
specifies which card should be used (this is only relevant if you have more
|
||||
than one sound card). Omit to use the default sound card.
|
||||
.. class:: Mixer(control='Master', id=0, cardindex=0)
|
||||
|
||||
This class is used to access a specific ALSA mixer. The arguments
|
||||
are:
|
||||
|
||||
* *control* - Name of the chosen mixed (default is 'Master').
|
||||
* *id* - id of mixer -- More explanation needed here
|
||||
* *cardindex* specifies which card should be used.
|
||||
|
||||
.. exception:: ALSAAudioError
|
||||
|
||||
Exception raised when an operation fails for a ALSA specific reason. The
|
||||
exception argument is a string describing the reason of the failure.
|
||||
|
||||
|
||||
.. _pcm-objects:
|
||||
|
||||
PCM Objects
|
||||
-----------
|
||||
|
||||
The acronym PCM is short for Pulse Code Modulation and is the method used in
|
||||
ALSA and many other places to handle playback and capture of sampled
|
||||
sound data.
|
||||
|
||||
PCM objects in :mod:`alsaaudio` are used to do exactly that, either
|
||||
play sample based sound or capture sound from some input source
|
||||
(probably a microphone). The PCM object constructor takes the
|
||||
PCM objects in :mod:`alsaaudio` can play or capture (record) PCM
|
||||
sound through speakers or a microphone. The PCM constructor takes the
|
||||
following arguments:
|
||||
|
||||
.. class:: PCM(type=PCM_CAPTURE, mode=PCM_NORMAL, card='default')
|
||||
|
||||
.. class:: PCM([type], [mode], [cardname])
|
||||
*type* - can be either ``PCM_CAPTURE`` or ``PCM_PLAYBACK`` (default).
|
||||
|
||||
*type* - can be either PCM_CAPTURE or PCM_PLAYBACK (default).
|
||||
*mode* - can be either ``PCM_NONBLOCK``, or ``PCM_NORMAL`` (the
|
||||
default). In ``PCM_NONBLOCK`` mode, calls to :func:`read` will return
|
||||
immediately independent of whether there is any actual data to
|
||||
read. Similarly, calls to :func:`write` will return immediately without
|
||||
actually writing anything to the playout buffer if the buffer is
|
||||
full [#f1]_.
|
||||
|
||||
*mode* - can be either PCM_NONBLOCK, PCM_ASYNC, or PCM_NORMAL (the
|
||||
default). In PCM_NONBLOCK mode, calls to read will return
|
||||
immediately independent of wether there is any actual data to
|
||||
read. Similarly, write calls will return immediately without
|
||||
actually writing anything to the playout buffer if the buffer is full.
|
||||
*card* - specifies which card should be used. This can be a string
|
||||
like 'default' or a name that was returned from the :func:`cards` function.
|
||||
|
||||
In the current version of :mod:`alsaaudio` PCM_ASYNC is useless,
|
||||
since it relies on a callback procedure, which can't be specified
|
||||
through this API yet.
|
||||
This will construct a PCM object with these default settings:
|
||||
|
||||
*cardname* - specifies which card should be used (this is only
|
||||
relevant if you have more than one sound card). Omit to use the
|
||||
default sound card.
|
||||
|
||||
This will construct a PCM object with default settings:
|
||||
|
||||
Sample format: PCM_FORMAT_S16_LE --- Rate: 8000 Hz --- Channels: 2 ---
|
||||
Period size: 32 frames ---
|
||||
* Sample format: ``PCM_FORMAT_S16_LE``
|
||||
* Rate: 44100 Hz
|
||||
* Channels: 2
|
||||
* Period size: 32 frames
|
||||
|
||||
PCM objects have the following methods:
|
||||
|
||||
@@ -304,7 +218,7 @@ ugly clicking sounds will occur. Conversely, of too much data is
|
||||
written to the device, the write function will either block
|
||||
(PCM_NORMAL mode) or return zero (PCM_NONBLOCK mode).
|
||||
|
||||
If your program does nothing, but play sound, the easiest way is to put the
|
||||
If your program does nothing but play sound, the best strategy is to put the
|
||||
device in PCM_NORMAL mode, and just write as much data to the device as
|
||||
possible. This strategy can also be achieved by using a separate
|
||||
thread with the sole task of playing out sound.
|
||||
@@ -330,7 +244,7 @@ Mixer Objects
|
||||
Mixer objects provides access to the ALSA mixer API.
|
||||
|
||||
|
||||
.. class:: Mixer([control], [id], [cardname])
|
||||
.. class:: Mixer([control], [id], [cardindex])
|
||||
|
||||
*control* - specifies which control to manipulate using this mixer
|
||||
object. The list of available controls can be found with the
|
||||
@@ -339,9 +253,12 @@ Mixer objects provides access to the ALSA mixer API.
|
||||
|
||||
*id* - the id of the mixer control. Default is 0
|
||||
|
||||
*cardname* - specifies which card should be used (this is only
|
||||
relevant if you have more than one sound card). Omit to use the
|
||||
default sound card.
|
||||
*cardindex* - specifies which card should be used[#f3]_. 0 is the
|
||||
first sound card. Default is 0.
|
||||
|
||||
For a list of available controls, you can also use ``amixer``::
|
||||
|
||||
amixer -c 1
|
||||
|
||||
Mixer objects have the following methods:
|
||||
|
||||
@@ -498,7 +415,7 @@ Mixer objects have the following methods:
|
||||
|
||||
This method will fail if the mixer has no capture switch capabilities.
|
||||
|
||||
**A Note on the ALSA Mixer API**
|
||||
**A rant on the ALSA Mixer API**
|
||||
|
||||
The ALSA mixer API is extremely complicated - and hardly documented at all.
|
||||
:mod:`alsaaudio` implements a much simplified way to access this API. In
|
||||
@@ -525,9 +442,56 @@ painful trial and error process.
|
||||
|
||||
.. _pcm-example:
|
||||
|
||||
ALSA Examples
|
||||
-------------
|
||||
Examples
|
||||
--------
|
||||
|
||||
For now, the only examples available are the 'playbacktest.py' and the
|
||||
'recordtest.py' programs included. This will change in a future version.
|
||||
The following examples are provided:
|
||||
|
||||
* playwav.py
|
||||
* recordtest.py
|
||||
* playbacktest.py
|
||||
|
||||
All examples take the commandline option '-c <cardname>'.
|
||||
|
||||
To determine a valid card name, use the commandline ALSA player::
|
||||
|
||||
$ aplay -L
|
||||
|
||||
or::
|
||||
|
||||
$ python
|
||||
|
||||
>>> import alsaaudio
|
||||
>>> alsaaudio.cards()
|
||||
|
||||
playwav.py
|
||||
~~~~~~~~~~
|
||||
|
||||
``playwav.py`` plays a wav file. A sample wav file is
|
||||
provided in the source distribution.
|
||||
|
||||
To test PCM playback (on your default soundcard), do::
|
||||
|
||||
$ python playwav.py foo.wav
|
||||
|
||||
recordtest.py and playbacktest.py
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
``recordtest.py`` and ``playbacktest.py`` will record and play a raw
|
||||
sound file in CD quality.
|
||||
|
||||
To test PCM recordings (on your default soundcard), do::
|
||||
|
||||
$ python recordtest.py <filename>
|
||||
|
||||
Speak into the microphone, and interrupt the recording at any time
|
||||
with ``Ctl-C``.
|
||||
|
||||
Play back the recording with::
|
||||
|
||||
$ python playbacktest.py <filename>
|
||||
|
||||
.. rubric:: Footnotes
|
||||
|
||||
.. [#f1] ALSA also allows ``PCM_ASYNC``, but this is not supported yet.
|
||||
.. [#f2] But :mod:`alsaaudio` will leave any name alone that has a ':' (colon) in it.
|
||||
.. [#f3] This is inconsistent with the PCM objects, which use names, but it is consistent with aplay and amixer.
|
||||
|
||||
@@ -1,407 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<link rel="STYLESHEET" href="pyalsaaudio.css" type='text/css' />
|
||||
<link rel="first" href="pyalsaaudio.html" title='PyAlsaAudio' />
|
||||
<link rel='contents' href='contents.html' title="Contents" />
|
||||
<link rel='last' href='about.html' title='About this document...' />
|
||||
<link rel='help' href='about.html' title='About this document...' />
|
||||
<link rel="next" href="pcm-example.html" />
|
||||
<link rel="prev" href="pcm-objects.html" />
|
||||
<link rel="parent" href="module-alsaaudio.html" />
|
||||
<link rel="next" href="pcm-example.html" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name='aesop' content='information' />
|
||||
<title>4.3 Mixer Objects</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="navigation">
|
||||
<div id='top-navigation-panel' xml:id='top-navigation-panel'>
|
||||
<table align="center" width="100%" cellpadding="0" cellspacing="2">
|
||||
<tr>
|
||||
<td class='online-navigation'><a rel="prev" title="4.2 pcm Objects"
|
||||
href="pcm-objects.html"><img src='previous.png'
|
||||
border='0' height='32' alt='Previous Page' width='32' /></a></td>
|
||||
<td class='online-navigation'><a rel="parent" title="4 alsaaudio"
|
||||
href="module-alsaaudio.html"><img src='up.png'
|
||||
border='0' height='32' alt='Up one Level' width='32' /></a></td>
|
||||
<td class='online-navigation'><a rel="next" title="4.4 alsa Examples"
|
||||
href="pcm-example.html"><img src='next.png'
|
||||
border='0' height='32' alt='Next Page' width='32' /></a></td>
|
||||
<td align="center" width="100%">PyAlsaAudio</td>
|
||||
<td class='online-navigation'><a rel="contents" title="Table of Contents"
|
||||
href="contents.html"><img src='contents.png'
|
||||
border='0' height='32' alt='Contents' width='32' /></a></td>
|
||||
<td class='online-navigation'><img src='blank.png'
|
||||
border='0' height='32' alt='' width='32' /></td>
|
||||
<td class='online-navigation'><img src='blank.png'
|
||||
border='0' height='32' alt='' width='32' /></td>
|
||||
</tr></table>
|
||||
<div class='online-navigation'>
|
||||
<b class="navlabel">Previous:</b>
|
||||
<a class="sectref" rel="prev" href="pcm-objects.html">4.2 PCM Objects</a>
|
||||
<b class="navlabel">Up:</b>
|
||||
<a class="sectref" rel="parent" href="module-alsaaudio.html">4 alsaaudio</a>
|
||||
<b class="navlabel">Next:</b>
|
||||
<a class="sectref" rel="next" href="pcm-example.html">4.4 ALSA Examples</a>
|
||||
</div>
|
||||
<hr /></div>
|
||||
</div>
|
||||
<!--End of Navigation Panel-->
|
||||
|
||||
<h2><a name="SECTION002430000000000000000"></a>
|
||||
<a name="mixer-objects"></a>
|
||||
<br>
|
||||
4.3 Mixer Objects
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
Mixer objects provides access to the ALSA mixer API.
|
||||
|
||||
<p>
|
||||
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
|
||||
<td><nobr><b><span class="typelabel">class</span> <tt id='l2h-17' xml:id='l2h-17' class="class">Mixer</tt></b>(</nobr></td>
|
||||
<td><var></var><big>[</big><var>control</var><big>]</big><var>, </var><big>[</big><var>id</var><big>]</big><var>,
|
||||
</var><big>[</big><var>cardname</var><big>]</big><var></var>)</td></tr></table></dt>
|
||||
<dd>
|
||||
<var>control</var> - specifies which control to manipulate using this
|
||||
mixer object. The list of available controls can be found with the
|
||||
<tt class="module">alsaaudio</tt>.<tt class="function">mixers</tt> function. The default value is
|
||||
'Master' - other common controls include 'Master Mono', 'PCM',
|
||||
'Line', etc.
|
||||
|
||||
<p>
|
||||
<var>id</var> - the id of the mixer control. Default is 0
|
||||
|
||||
<p>
|
||||
<var>cardname</var> - specifies which card should be used (this is only
|
||||
relevant if you have more than one sound card). Omit to use the
|
||||
default sound card
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
Mixer objects have the following methods:
|
||||
|
||||
<p>
|
||||
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
|
||||
<td><nobr><b><tt id='l2h-18' xml:id='l2h-18' class="method">cardname</tt></b>(</nobr></td>
|
||||
<td><var></var>)</td></tr></table></dt>
|
||||
<dd>
|
||||
Return the name of the sound card used by this Mixer object
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
|
||||
<td><nobr><b><tt id='l2h-19' xml:id='l2h-19' class="method">mixer</tt></b>(</nobr></td>
|
||||
<td><var></var>)</td></tr></table></dt>
|
||||
<dd>
|
||||
Return the name of the specific mixer controlled by this object, For
|
||||
example 'Master' or 'PCM'
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
|
||||
<td><nobr><b><tt id='l2h-20' xml:id='l2h-20' class="method">mixerid</tt></b>(</nobr></td>
|
||||
<td><var></var>)</td></tr></table></dt>
|
||||
<dd>
|
||||
Return the ID of the ALSA mixer controlled by this object.
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
|
||||
<td><nobr><b><tt id='l2h-21' xml:id='l2h-21' class="method">switchcap</tt></b>(</nobr></td>
|
||||
<td><var></var>)</td></tr></table></dt>
|
||||
<dd>
|
||||
Returns a list of the switches which are defined by this specific
|
||||
mixer. Possible values in this list are:
|
||||
|
||||
<p>
|
||||
<div class="center"><table class="realtable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="left" >Switch</th>
|
||||
<th class="left" >Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td class="left" valign="baseline"><volume capabilities>'Mute'</volume></td>
|
||||
<td class="left" >This mixer can be muted</td></tr>
|
||||
<tr><td class="left" valign="baseline"><volume capabilities>'Joined Mute'</volume></td>
|
||||
<td class="left" >This mixer can mute all channels at the same time</td></tr>
|
||||
<tr><td class="left" valign="baseline"><volume capabilities>'Playback Mute'</volume></td>
|
||||
<td class="left" >This mixer can mute the playback output</td></tr>
|
||||
<tr><td class="left" valign="baseline"><volume capabilities>'Joined Playback Mute'</volume></td>
|
||||
<td class="left" >Mute playback for all channels at the same time</td></tr>
|
||||
<tr><td class="left" valign="baseline"><volume capabilities>'Capture Mute'</volume></td>
|
||||
<td class="left" >Mute sound capture</td></tr>
|
||||
<tr><td class="left" valign="baseline"><volume capabilities>'Joined Capture Mute'</volume></td>
|
||||
<td class="left" >Mute sound capture for all channels at a time</td></tr>
|
||||
<tr><td class="left" valign="baseline"><volume capabilities>'Capture Exclusive'</volume></td>
|
||||
<td class="left" >Not quite sure what this is</td></tr></tbody>
|
||||
</table></div>
|
||||
|
||||
<p>
|
||||
To manipulate these swithes use the <tt class="method">setrec</tt> or
|
||||
<tt class="method">setmute</tt> methods
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
|
||||
<td><nobr><b><tt id='l2h-22' xml:id='l2h-22' class="method">volumecap</tt></b>(</nobr></td>
|
||||
<td><var></var>)</td></tr></table></dt>
|
||||
<dd>
|
||||
Returns a list of the volume control capabilities of this mixer.
|
||||
Possible values in the list are:
|
||||
|
||||
<p>
|
||||
<div class="center"><table class="realtable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="left" >Capability</th>
|
||||
<th class="left" >Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td class="left" valign="baseline"><volume capabilities>'Volume'</volume></td>
|
||||
<td class="left" >This mixer can control volume</td></tr>
|
||||
<tr><td class="left" valign="baseline"><volume capabilities>'Joined Volume'</volume></td>
|
||||
<td class="left" >This mixer can control volume for all channels at
|
||||
the same time</td></tr>
|
||||
<tr><td class="left" valign="baseline"><volume capabilities>'Playback Volume'</volume></td>
|
||||
<td class="left" >This mixer can manipulate the playback volume</td></tr>
|
||||
<tr><td class="left" valign="baseline"><volume capabilities>'Joined Playback Volume'</volume></td>
|
||||
<td class="left" >Manipulate playback volumne for all
|
||||
channels at the same time</td></tr>
|
||||
<tr><td class="left" valign="baseline"><volume capabilities>'Capture Volume'</volume></td>
|
||||
<td class="left" >Manipulate sound capture volume</td></tr>
|
||||
<tr><td class="left" valign="baseline"><volume capabilities>'Joined Capture Volume'</volume></td>
|
||||
<td class="left" >Manipulate sound capture volume for all
|
||||
channels at a time</td></tr></tbody>
|
||||
</table></div>
|
||||
|
||||
<p>
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
|
||||
<td><nobr><b><tt id='l2h-23' xml:id='l2h-23' class="method">getenum</tt></b>(</nobr></td>
|
||||
<td><var></var>)</td></tr></table></dt>
|
||||
<dd>
|
||||
For enumerated controls, return the currently selected item and
|
||||
the list of items available.
|
||||
|
||||
<p>
|
||||
Returns a tuple <i>(string, list of strings)</i>.
|
||||
|
||||
<p>
|
||||
For example, my soundcard has a Mixer called <i>Mono Output Select</i>.
|
||||
Using <i>amixer</i>, I get:
|
||||
|
||||
<p>
|
||||
<div class="verbatim"><pre>
|
||||
$ amixer get "Mono Output Select"
|
||||
Simple mixer control 'Mono Output Select',0
|
||||
Capabilities: enum
|
||||
Items: 'Mix' 'Mic'
|
||||
Item0: 'Mix'
|
||||
</pre></div>
|
||||
|
||||
<p>
|
||||
Using <tt class="module">alsaaudio</tt>, one could do:
|
||||
<div class="verbatim"><pre>
|
||||
>>> import alsaaudio
|
||||
>>> m = alsaaudio.Mixer('Mono Output Select')
|
||||
>>> m.getenum()
|
||||
('Mix', ['Mix', 'Mic'])
|
||||
</pre></div>
|
||||
|
||||
<p>
|
||||
This method will return an empty tuple if the mixer is not an
|
||||
enumerated control.
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
|
||||
<td><nobr><b><tt id='l2h-24' xml:id='l2h-24' class="method">getmute</tt></b>(</nobr></td>
|
||||
<td><var></var>)</td></tr></table></dt>
|
||||
<dd>
|
||||
Return a list indicating the current mute setting for each channel.
|
||||
0 means not muted, 1 means muted.
|
||||
|
||||
<p>
|
||||
This method will fail if the mixer has no playback switch
|
||||
capabilities.
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
|
||||
<td><nobr><b><tt id='l2h-25' xml:id='l2h-25' class="method">getrange</tt></b>(</nobr></td>
|
||||
<td><var></var><big>[</big><var>direction</var><big>]</big><var></var>)</td></tr></table></dt>
|
||||
<dd>
|
||||
Return the volume range of the ALSA mixer controlled by this object.
|
||||
|
||||
<p>
|
||||
The optional <var>direction</var> argument can be either 'playback' or
|
||||
'capture', which is relevant if the mixer can control both playback
|
||||
and capture volume. The default value is 'playback' if the mixer
|
||||
has this capability, otherwise 'capture'
|
||||
|
||||
<p>
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
|
||||
<td><nobr><b><tt id='l2h-26' xml:id='l2h-26' class="method">getrec</tt></b>(</nobr></td>
|
||||
<td><var></var>)</td></tr></table></dt>
|
||||
<dd>
|
||||
Return a list indicating the current record mute setting for each
|
||||
channel. 0 means not recording, 1 means recording.
|
||||
|
||||
<p>
|
||||
This method will fail if the mixer has no capture switch
|
||||
capabilities.
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
|
||||
<td><nobr><b><tt id='l2h-27' xml:id='l2h-27' class="method">getvolume</tt></b>(</nobr></td>
|
||||
<td><var></var><big>[</big><var>direction</var><big>]</big><var></var>)</td></tr></table></dt>
|
||||
<dd>
|
||||
Returns a list with the current volume settings for each channel.
|
||||
The list elements are integer percentages.
|
||||
|
||||
<p>
|
||||
The optional <var>direction</var> argument can be either 'playback' or
|
||||
'capture', which is relevant if the mixer can control both playback
|
||||
and capture volume. The default value is 'playback' if the mixer has
|
||||
this capability, otherwise 'capture'
|
||||
|
||||
<p>
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
|
||||
<td><nobr><b><tt id='l2h-28' xml:id='l2h-28' class="method">setvolume</tt></b>(</nobr></td>
|
||||
<td><var>volume,</var><big>[</big><var>channel</var><big>]</big><var>,
|
||||
</var><big>[</big><var>direction</var><big>]</big><var></var>)</td></tr></table></dt>
|
||||
<dd>
|
||||
|
||||
<p>
|
||||
Change the current volume settings for this mixer. The <var>volume</var>
|
||||
argument controls the new volume setting as an integer percentage.
|
||||
|
||||
<p>
|
||||
If the optional argument <var>channel</var> is present, the volume is set
|
||||
only for this channel. This assumes that the mixer can control the
|
||||
volume for the channels independently.
|
||||
|
||||
<p>
|
||||
The optional <var>direction</var> argument can be either 'playback' or
|
||||
'capture' is relevant if the mixer has independent playback and
|
||||
capture volume capabilities, and controls which of the volumes if
|
||||
changed. The default is 'playback' if the mixer has this capability,
|
||||
otherwise 'capture'.
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
|
||||
<td><nobr><b><tt id='l2h-29' xml:id='l2h-29' class="method">setmute</tt></b>(</nobr></td>
|
||||
<td><var>mute, </var><big>[</big><var>channel</var><big>]</big><var></var>)</td></tr></table></dt>
|
||||
<dd>
|
||||
Sets the mute flag to a new value. The <var>mute</var> argument is either
|
||||
0 for not muted, or 1 for muted.
|
||||
|
||||
<p>
|
||||
The optional <var>channel</var> argument controls which channel is muted.
|
||||
The default is to set the mute flag for all channels.
|
||||
|
||||
<p>
|
||||
This method will fail if the mixer has no playback mute capabilities
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
|
||||
<td><nobr><b><tt id='l2h-30' xml:id='l2h-30' class="method">setrec</tt></b>(</nobr></td>
|
||||
<td><var>capture,</var><big>[</big><var>channel</var><big>]</big><var></var>)</td></tr></table></dt>
|
||||
<dd>
|
||||
Sets the capture mute flag to a new value. The <var>capture</var>
|
||||
argument is either 0 for no capture, or 1 for capture.
|
||||
|
||||
<p>
|
||||
The optional <var>channel</var> argument controls which channel is
|
||||
changed. The default is to set the capture flag for all channels.
|
||||
|
||||
<p>
|
||||
This method will fail if the mixer has no capture switch
|
||||
capabilities.
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
<b>A Note on the ALSA Mixer API</b>
|
||||
|
||||
<p>
|
||||
The ALSA mixer API is extremely complicated - and hardly documented at
|
||||
all. <tt class="module">alsaaudio</tt> implements a much simplified way to access
|
||||
this API. In designing the API I've had to make some choices which may
|
||||
limit what can and cannot be controlled through the API. However, If I
|
||||
had chosen to implement the full API, I would have reexposed the
|
||||
horrible complexity/documentation ratio of the underlying API. At
|
||||
least the <tt class="module">alsaaudio</tt> API is easy to understand and use.
|
||||
|
||||
<p>
|
||||
If my design choises prevents you from doing something that the
|
||||
underlying API would have allowed, please let me know, so I can
|
||||
incorporate these need into future versions.
|
||||
|
||||
<p>
|
||||
If the current state of affairs annoy you, the best you can do is to
|
||||
write a HOWTO on the API and make this available on the net. Until
|
||||
somebody does this, the availability of ALSA mixer capable devices
|
||||
will stay quite limited.
|
||||
|
||||
<p>
|
||||
Unfortunately, I'm not able to create such a HOWTO myself, since I
|
||||
only understand half of the API, and that which I do understand has
|
||||
come from a painful trial and error process.
|
||||
|
||||
<p>
|
||||
|
||||
<div class="navigation">
|
||||
<div class='online-navigation'>
|
||||
<p></p><hr />
|
||||
<table align="center" width="100%" cellpadding="0" cellspacing="2">
|
||||
<tr>
|
||||
<td class='online-navigation'><a rel="prev" title="4.2 pcm Objects"
|
||||
href="pcm-objects.html"><img src='previous.png'
|
||||
border='0' height='32' alt='Previous Page' width='32' /></a></td>
|
||||
<td class='online-navigation'><a rel="parent" title="4 alsaaudio"
|
||||
href="module-alsaaudio.html"><img src='up.png'
|
||||
border='0' height='32' alt='Up one Level' width='32' /></a></td>
|
||||
<td class='online-navigation'><a rel="next" title="4.4 alsa Examples"
|
||||
href="pcm-example.html"><img src='next.png'
|
||||
border='0' height='32' alt='Next Page' width='32' /></a></td>
|
||||
<td align="center" width="100%">PyAlsaAudio</td>
|
||||
<td class='online-navigation'><a rel="contents" title="Table of Contents"
|
||||
href="contents.html"><img src='contents.png'
|
||||
border='0' height='32' alt='Contents' width='32' /></a></td>
|
||||
<td class='online-navigation'><img src='blank.png'
|
||||
border='0' height='32' alt='' width='32' /></td>
|
||||
<td class='online-navigation'><img src='blank.png'
|
||||
border='0' height='32' alt='' width='32' /></td>
|
||||
</tr></table>
|
||||
<div class='online-navigation'>
|
||||
<b class="navlabel">Previous:</b>
|
||||
<a class="sectref" rel="prev" href="pcm-objects.html">4.2 PCM Objects</a>
|
||||
<b class="navlabel">Up:</b>
|
||||
<a class="sectref" rel="parent" href="module-alsaaudio.html">4 alsaaudio</a>
|
||||
<b class="navlabel">Next:</b>
|
||||
<a class="sectref" rel="next" href="pcm-example.html">4.4 ALSA Examples</a>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<span class="release-info">Release 0.4.</span>
|
||||
</div>
|
||||
<!--End of Navigation Panel-->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,170 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<link rel="STYLESHEET" href="pyalsaaudio.css" type='text/css' />
|
||||
<link rel="first" href="pyalsaaudio.html" title='PyAlsaAudio' />
|
||||
<link rel='contents' href='contents.html' title="Contents" />
|
||||
<link rel='last' href='about.html' title='About this document...' />
|
||||
<link rel='help' href='about.html' title='About this document...' />
|
||||
<link rel="prev" href="node5.html" />
|
||||
<link rel="parent" href="contents.html" />
|
||||
<link rel="next" href="node7.html" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name='aesop' content='information' />
|
||||
<title>4 alsaaudio</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="navigation">
|
||||
<div id='top-navigation-panel' xml:id='top-navigation-panel'>
|
||||
<table align="center" width="100%" cellpadding="0" cellspacing="2">
|
||||
<tr>
|
||||
<td class='online-navigation'><a rel="prev" title="3 Installation"
|
||||
href="node5.html"><img src='previous.png'
|
||||
border='0' height='32' alt='Previous Page' width='32' /></a></td>
|
||||
<td class='online-navigation'><a rel="parent" title="Contents"
|
||||
href="contents.html"><img src='up.png'
|
||||
border='0' height='32' alt='Up one Level' width='32' /></a></td>
|
||||
<td class='online-navigation'><a rel="next" title="4.1 pcm Terminology and"
|
||||
href="node7.html"><img src='next.png'
|
||||
border='0' height='32' alt='Next Page' width='32' /></a></td>
|
||||
<td align="center" width="100%">PyAlsaAudio</td>
|
||||
<td class='online-navigation'><a rel="contents" title="Table of Contents"
|
||||
href="contents.html"><img src='contents.png'
|
||||
border='0' height='32' alt='Contents' width='32' /></a></td>
|
||||
<td class='online-navigation'><img src='blank.png'
|
||||
border='0' height='32' alt='' width='32' /></td>
|
||||
<td class='online-navigation'><img src='blank.png'
|
||||
border='0' height='32' alt='' width='32' /></td>
|
||||
</tr></table>
|
||||
<div class='online-navigation'>
|
||||
<b class="navlabel">Previous:</b>
|
||||
<a class="sectref" rel="prev" href="node5.html">3 Installation</a>
|
||||
<b class="navlabel">Up:</b>
|
||||
<a class="sectref" rel="parent" href="contents.html">Contents</a>
|
||||
<b class="navlabel">Next:</b>
|
||||
<a class="sectref" rel="next" href="node7.html">4.1 PCM Terminology and</a>
|
||||
</div>
|
||||
<hr /></div>
|
||||
</div>
|
||||
<!--End of Navigation Panel-->
|
||||
|
||||
<h1><a name="SECTION002400000000000000000">
|
||||
4 <tt class="module">alsaaudio</tt></a>
|
||||
</h1>
|
||||
|
||||
<p>
|
||||
<a name="module-alsaaudio"></a>
|
||||
<p>
|
||||
|
||||
<p class="availability">Availability: <span
|
||||
class="platform">Linux</span>.</p>
|
||||
|
||||
<p>
|
||||
|
||||
<p>
|
||||
|
||||
<p>
|
||||
The <tt class="module">alsaaudio</tt> module defines functions and classes for using
|
||||
ALSA.
|
||||
|
||||
<p>
|
||||
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
|
||||
<td><nobr><b><tt id='l2h-2' xml:id='l2h-2' class="function">mixers</tt></b>(</nobr></td>
|
||||
<td><var></var><big>[</big><var>cardname</var><big>]</big><var></var>)</td></tr></table></dt>
|
||||
<dd>
|
||||
List the available mixers. The optional <var>cardname</var> specifies which
|
||||
card should be queried (this is only relevant if you have more than one
|
||||
sound card). Omit to use the default sound card.
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
|
||||
<td><nobr><b><span class="typelabel">class</span> <tt id='l2h-3' xml:id='l2h-3' class="class">PCM</tt></b>(</nobr></td>
|
||||
<td><var></var><big>[</big><var>type</var><big>]</big><var>, </var><big>[</big><var>mode</var><big>]</big><var>, </var><big>[</big><var>cardname</var><big>]</big><var></var>)</td></tr></table></dt>
|
||||
<dd>
|
||||
This class is used to represent a PCM device (both playback and
|
||||
capture devices).
|
||||
The arguments are:
|
||||
<br> <var>type</var> - can be either PCM_CAPTURE or PCM_PLAYBACK (default).
|
||||
<br> <var>mode</var> - can be either PCM_NONBLOCK, PCM_ASYNC, or PCM_NORMAL (the default).
|
||||
<br> <var>cardname</var> - specifies which card should be used (this is only
|
||||
relevant if you have more than one sound card). Omit to use the
|
||||
default sound card
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
|
||||
<td><nobr><b><span class="typelabel">class</span> <tt id='l2h-4' xml:id='l2h-4' class="class">Mixer</tt></b>(</nobr></td>
|
||||
<td><var></var><big>[</big><var>control</var><big>]</big><var>, </var><big>[</big><var>id</var><big>]</big><var>, </var><big>[</big><var>cardname</var><big>]</big><var></var>)</td></tr></table></dt>
|
||||
<dd>
|
||||
This class is used to access a specific ALSA mixer.
|
||||
The arguments are:
|
||||
<br><var>control</var> - Name of the chosen mixed (default is Master).
|
||||
<br><var>id</var> - id of mixer (default is 0) - More explanation needed here
|
||||
<br><var>cardname</var> specifies which card should be used (this is only relevant
|
||||
if you have more than one sound card). Omit to use the default sound card
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
<dl><dt><b><span class="typelabel">exception</span> <tt id='l2h-5' xml:id='l2h-5' class="exception">ALSAAudioError</tt></b></dt>
|
||||
<dd>
|
||||
Exception raised when an operation fails for a ALSA specific reason.
|
||||
The exception argument is a string describing the reason of the
|
||||
failure.
|
||||
</dd></dl>
|
||||
|
||||
<p>
|
||||
|
||||
<p><br /></p><hr class='online-navigation' />
|
||||
<div class='online-navigation'>
|
||||
<!--Table of Child-Links-->
|
||||
<a name="CHILD_LINKS"><strong>Subsections</strong></a>
|
||||
|
||||
<ul class="ChildLinks">
|
||||
<li><a href="node7.html">4.1 PCM Terminology and Concepts</a>
|
||||
<li><a href="pcm-objects.html">4.2 PCM Objects</a>
|
||||
<li><a href="mixer-objects.html">4.3 Mixer Objects</a>
|
||||
<li><a href="pcm-example.html">4.4 ALSA Examples</a>
|
||||
</ul>
|
||||
<!--End of Table of Child-Links-->
|
||||
</div>
|
||||
|
||||
<div class="navigation">
|
||||
<div class='online-navigation'>
|
||||
<p></p><hr />
|
||||
<table align="center" width="100%" cellpadding="0" cellspacing="2">
|
||||
<tr>
|
||||
<td class='online-navigation'><a rel="prev" title="3 Installation"
|
||||
href="node5.html"><img src='previous.png'
|
||||
border='0' height='32' alt='Previous Page' width='32' /></a></td>
|
||||
<td class='online-navigation'><a rel="parent" title="Contents"
|
||||
href="contents.html"><img src='up.png'
|
||||
border='0' height='32' alt='Up one Level' width='32' /></a></td>
|
||||
<td class='online-navigation'><a rel="next" title="4.1 pcm Terminology and"
|
||||
href="node7.html"><img src='next.png'
|
||||
border='0' height='32' alt='Next Page' width='32' /></a></td>
|
||||
<td align="center" width="100%">PyAlsaAudio</td>
|
||||
<td class='online-navigation'><a rel="contents" title="Table of Contents"
|
||||
href="contents.html"><img src='contents.png'
|
||||
border='0' height='32' alt='Contents' width='32' /></a></td>
|
||||
<td class='online-navigation'><img src='blank.png'
|
||||
border='0' height='32' alt='' width='32' /></td>
|
||||
<td class='online-navigation'><img src='blank.png'
|
||||
border='0' height='32' alt='' width='32' /></td>
|
||||
</tr></table>
|
||||
<div class='online-navigation'>
|
||||
<b class="navlabel">Previous:</b>
|
||||
<a class="sectref" rel="prev" href="node5.html">3 Installation</a>
|
||||
<b class="navlabel">Up:</b>
|
||||
<a class="sectref" rel="parent" href="contents.html">Contents</a>
|
||||
<b class="navlabel">Next:</b>
|
||||
<a class="sectref" rel="next" href="node7.html">4.1 PCM Terminology and</a>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<span class="release-info">Release 0.4.</span>
|
||||
</div>
|
||||
<!--End of Navigation Panel-->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
-121
@@ -1,121 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<link rel="STYLESHEET" href="pyalsaaudio.css" type='text/css' />
|
||||
<link rel="first" href="pyalsaaudio.html" title='PyAlsaAudio' />
|
||||
<link rel='contents' href='contents.html' title="Contents" />
|
||||
<link rel='last' href='about.html' title='About this document...' />
|
||||
<link rel='help' href='about.html' title='About this document...' />
|
||||
<link rel="next" href="node4.html" />
|
||||
<link rel="prev" href="contents.html" />
|
||||
<link rel="parent" href="contents.html" />
|
||||
<link rel="next" href="node4.html" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name='aesop' content='information' />
|
||||
<title>1 What is ALSA</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="navigation">
|
||||
<div id='top-navigation-panel' xml:id='top-navigation-panel'>
|
||||
<table align="center" width="100%" cellpadding="0" cellspacing="2">
|
||||
<tr>
|
||||
<td class='online-navigation'><a rel="prev" title="Contents"
|
||||
href="contents.html"><img src='previous.png'
|
||||
border='0' height='32' alt='Previous Page' width='32' /></a></td>
|
||||
<td class='online-navigation'><a rel="parent" title="Contents"
|
||||
href="contents.html"><img src='up.png'
|
||||
border='0' height='32' alt='Up one Level' width='32' /></a></td>
|
||||
<td class='online-navigation'><a rel="next" title="2 alsa and Python"
|
||||
href="node4.html"><img src='next.png'
|
||||
border='0' height='32' alt='Next Page' width='32' /></a></td>
|
||||
<td align="center" width="100%">PyAlsaAudio</td>
|
||||
<td class='online-navigation'><a rel="contents" title="Table of Contents"
|
||||
href="contents.html"><img src='contents.png'
|
||||
border='0' height='32' alt='Contents' width='32' /></a></td>
|
||||
<td class='online-navigation'><img src='blank.png'
|
||||
border='0' height='32' alt='' width='32' /></td>
|
||||
<td class='online-navigation'><img src='blank.png'
|
||||
border='0' height='32' alt='' width='32' /></td>
|
||||
</tr></table>
|
||||
<div class='online-navigation'>
|
||||
<b class="navlabel">Previous:</b>
|
||||
<a class="sectref" rel="prev" href="contents.html">Contents</a>
|
||||
<b class="navlabel">Up:</b>
|
||||
<a class="sectref" rel="parent" href="contents.html">Contents</a>
|
||||
<b class="navlabel">Next:</b>
|
||||
<a class="sectref" rel="next" href="node4.html">2 ALSA and Python</a>
|
||||
</div>
|
||||
<hr /></div>
|
||||
</div>
|
||||
<!--End of Navigation Panel-->
|
||||
|
||||
<h1><a name="SECTION002100000000000000000">
|
||||
1 What is ALSA</a>
|
||||
</h1>
|
||||
|
||||
<p>
|
||||
The Advanced Linux Sound Architecture (ALSA) provides audio and MIDI
|
||||
functionality to the Linux operating system.
|
||||
|
||||
<p>
|
||||
Logically ALSA consists of these components:
|
||||
|
||||
<ul>
|
||||
<li>A set of kernel drivers.
|
||||
<br>
|
||||
These drivers are responsible for handling the physical sound
|
||||
hardware from within the Linux kernel, and have been the standard
|
||||
sound implementation in Linux since kernel version 2.5
|
||||
</li>
|
||||
<li>A kernel level API for manipulating the ALSA devices.
|
||||
</li>
|
||||
<li>A user-space C library for simplified access to the sound hardware
|
||||
from userspace applications. This library is called <i>libasound</i>
|
||||
and is required by all ALSA capable applications.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
More information about ALSA may be found on the project homepage
|
||||
<a class="url" href="http://www.alsa-project.org">http://www.alsa-project.org</a>
|
||||
<p>
|
||||
|
||||
<div class="navigation">
|
||||
<div class='online-navigation'>
|
||||
<p></p><hr />
|
||||
<table align="center" width="100%" cellpadding="0" cellspacing="2">
|
||||
<tr>
|
||||
<td class='online-navigation'><a rel="prev" title="Contents"
|
||||
href="contents.html"><img src='previous.png'
|
||||
border='0' height='32' alt='Previous Page' width='32' /></a></td>
|
||||
<td class='online-navigation'><a rel="parent" title="Contents"
|
||||
href="contents.html"><img src='up.png'
|
||||
border='0' height='32' alt='Up one Level' width='32' /></a></td>
|
||||
<td class='online-navigation'><a rel="next" title="2 alsa and Python"
|
||||
href="node4.html"><img src='next.png'
|
||||
border='0' height='32' alt='Next Page' width='32' /></a></td>
|
||||
<td align="center" width="100%">PyAlsaAudio</td>
|
||||
<td class='online-navigation'><a rel="contents" title="Table of Contents"
|
||||
href="contents.html"><img src='contents.png'
|
||||
border='0' height='32' alt='Contents' width='32' /></a></td>
|
||||
<td class='online-navigation'><img src='blank.png'
|
||||
border='0' height='32' alt='' width='32' /></td>
|
||||
<td class='online-navigation'><img src='blank.png'
|
||||
border='0' height='32' alt='' width='32' /></td>
|
||||
</tr></table>
|
||||
<div class='online-navigation'>
|
||||
<b class="navlabel">Previous:</b>
|
||||
<a class="sectref" rel="prev" href="contents.html">Contents</a>
|
||||
<b class="navlabel">Up:</b>
|
||||
<a class="sectref" rel="parent" href="contents.html">Contents</a>
|
||||
<b class="navlabel">Next:</b>
|
||||
<a class="sectref" rel="next" href="node4.html">2 ALSA and Python</a>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<span class="release-info">Release 0.4.</span>
|
||||
</div>
|
||||
<!--End of Navigation Panel-->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
-119
@@ -1,119 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<link rel="STYLESHEET" href="pyalsaaudio.css" type='text/css' />
|
||||
<link rel="first" href="pyalsaaudio.html" title='PyAlsaAudio' />
|
||||
<link rel='contents' href='contents.html' title="Contents" />
|
||||
<link rel='last' href='about.html' title='About this document...' />
|
||||
<link rel='help' href='about.html' title='About this document...' />
|
||||
<link rel="next" href="node5.html" />
|
||||
<link rel="prev" href="node3.html" />
|
||||
<link rel="parent" href="contents.html" />
|
||||
<link rel="next" href="node5.html" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name='aesop' content='information' />
|
||||
<title>2 ALSA and Python</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="navigation">
|
||||
<div id='top-navigation-panel' xml:id='top-navigation-panel'>
|
||||
<table align="center" width="100%" cellpadding="0" cellspacing="2">
|
||||
<tr>
|
||||
<td class='online-navigation'><a rel="prev" title="1 what is ALSA"
|
||||
href="node3.html"><img src='previous.png'
|
||||
border='0' height='32' alt='Previous Page' width='32' /></a></td>
|
||||
<td class='online-navigation'><a rel="parent" title="Contents"
|
||||
href="contents.html"><img src='up.png'
|
||||
border='0' height='32' alt='Up one Level' width='32' /></a></td>
|
||||
<td class='online-navigation'><a rel="next" title="3 Installation"
|
||||
href="node5.html"><img src='next.png'
|
||||
border='0' height='32' alt='Next Page' width='32' /></a></td>
|
||||
<td align="center" width="100%">PyAlsaAudio</td>
|
||||
<td class='online-navigation'><a rel="contents" title="Table of Contents"
|
||||
href="contents.html"><img src='contents.png'
|
||||
border='0' height='32' alt='Contents' width='32' /></a></td>
|
||||
<td class='online-navigation'><img src='blank.png'
|
||||
border='0' height='32' alt='' width='32' /></td>
|
||||
<td class='online-navigation'><img src='blank.png'
|
||||
border='0' height='32' alt='' width='32' /></td>
|
||||
</tr></table>
|
||||
<div class='online-navigation'>
|
||||
<b class="navlabel">Previous:</b>
|
||||
<a class="sectref" rel="prev" href="node3.html">1 What is ALSA</a>
|
||||
<b class="navlabel">Up:</b>
|
||||
<a class="sectref" rel="parent" href="contents.html">Contents</a>
|
||||
<b class="navlabel">Next:</b>
|
||||
<a class="sectref" rel="next" href="node5.html">3 Installation</a>
|
||||
</div>
|
||||
<hr /></div>
|
||||
</div>
|
||||
<!--End of Navigation Panel-->
|
||||
|
||||
<h1><a name="SECTION002200000000000000000">
|
||||
2 ALSA and Python</a>
|
||||
</h1>
|
||||
|
||||
<p>
|
||||
The older Linux sound API (OSS) which is now deprecated is well
|
||||
supported from the standard Python library, through the ossaudiodev
|
||||
module. No native ALSA support exists in the standard library (yet).
|
||||
|
||||
<p>
|
||||
There are a few other ``ALSA for Python'' projects available,
|
||||
including at least two different projects called pyAlsa. Neither of
|
||||
these seem to be under active development at the time - and neither
|
||||
are very feature complete.
|
||||
|
||||
<p>
|
||||
I wrote PyAlsaAudio to fill this gap. My long term goal is to have the
|
||||
module included in the standard Python library, but that is probably a
|
||||
while off yet.
|
||||
|
||||
<p>
|
||||
PyAlsaAudio hass full support for sound capture, playback of sound, as
|
||||
well as the ALSA Mixer API.
|
||||
|
||||
<p>
|
||||
MIDI support is not available, and since I don't own any MIDI
|
||||
hardware, it's difficult for me to implement it. Volunteers to work on
|
||||
this would be greatly appreciated
|
||||
|
||||
<div class="navigation">
|
||||
<div class='online-navigation'>
|
||||
<p></p><hr />
|
||||
<table align="center" width="100%" cellpadding="0" cellspacing="2">
|
||||
<tr>
|
||||
<td class='online-navigation'><a rel="prev" title="1 what is ALSA"
|
||||
href="node3.html"><img src='previous.png'
|
||||
border='0' height='32' alt='Previous Page' width='32' /></a></td>
|
||||
<td class='online-navigation'><a rel="parent" title="Contents"
|
||||
href="contents.html"><img src='up.png'
|
||||
border='0' height='32' alt='Up one Level' width='32' /></a></td>
|
||||
<td class='online-navigation'><a rel="next" title="3 Installation"
|
||||
href="node5.html"><img src='next.png'
|
||||
border='0' height='32' alt='Next Page' width='32' /></a></td>
|
||||
<td align="center" width="100%">PyAlsaAudio</td>
|
||||
<td class='online-navigation'><a rel="contents" title="Table of Contents"
|
||||
href="contents.html"><img src='contents.png'
|
||||
border='0' height='32' alt='Contents' width='32' /></a></td>
|
||||
<td class='online-navigation'><img src='blank.png'
|
||||
border='0' height='32' alt='' width='32' /></td>
|
||||
<td class='online-navigation'><img src='blank.png'
|
||||
border='0' height='32' alt='' width='32' /></td>
|
||||
</tr></table>
|
||||
<div class='online-navigation'>
|
||||
<b class="navlabel">Previous:</b>
|
||||
<a class="sectref" rel="prev" href="node3.html">1 What is ALSA</a>
|
||||
<b class="navlabel">Up:</b>
|
||||
<a class="sectref" rel="parent" href="contents.html">Contents</a>
|
||||
<b class="navlabel">Next:</b>
|
||||
<a class="sectref" rel="next" href="node5.html">3 Installation</a>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<span class="release-info">Release 0.4.</span>
|
||||
</div>
|
||||
<!--End of Navigation Panel-->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
-123
@@ -1,123 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<link rel="STYLESHEET" href="pyalsaaudio.css" type='text/css' />
|
||||
<link rel="first" href="pyalsaaudio.html" title='PyAlsaAudio' />
|
||||
<link rel='contents' href='contents.html' title="Contents" />
|
||||
<link rel='last' href='about.html' title='About this document...' />
|
||||
<link rel='help' href='about.html' title='About this document...' />
|
||||
<link rel="next" href="module-alsaaudio.html" />
|
||||
<link rel="prev" href="node4.html" />
|
||||
<link rel="parent" href="contents.html" />
|
||||
<link rel="next" href="module-alsaaudio.html" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name='aesop' content='information' />
|
||||
<title>3 Installation</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="navigation">
|
||||
<div id='top-navigation-panel' xml:id='top-navigation-panel'>
|
||||
<table align="center" width="100%" cellpadding="0" cellspacing="2">
|
||||
<tr>
|
||||
<td class='online-navigation'><a rel="prev" title="2 alsa and Python"
|
||||
href="node4.html"><img src='previous.png'
|
||||
border='0' height='32' alt='Previous Page' width='32' /></a></td>
|
||||
<td class='online-navigation'><a rel="parent" title="Contents"
|
||||
href="contents.html"><img src='up.png'
|
||||
border='0' height='32' alt='Up one Level' width='32' /></a></td>
|
||||
<td class='online-navigation'><a rel="next" title="4 alsaaudio"
|
||||
href="module-alsaaudio.html"><img src='next.png'
|
||||
border='0' height='32' alt='Next Page' width='32' /></a></td>
|
||||
<td align="center" width="100%">PyAlsaAudio</td>
|
||||
<td class='online-navigation'><a rel="contents" title="Table of Contents"
|
||||
href="contents.html"><img src='contents.png'
|
||||
border='0' height='32' alt='Contents' width='32' /></a></td>
|
||||
<td class='online-navigation'><img src='blank.png'
|
||||
border='0' height='32' alt='' width='32' /></td>
|
||||
<td class='online-navigation'><img src='blank.png'
|
||||
border='0' height='32' alt='' width='32' /></td>
|
||||
</tr></table>
|
||||
<div class='online-navigation'>
|
||||
<b class="navlabel">Previous:</b>
|
||||
<a class="sectref" rel="prev" href="node4.html">2 ALSA and Python</a>
|
||||
<b class="navlabel">Up:</b>
|
||||
<a class="sectref" rel="parent" href="contents.html">Contents</a>
|
||||
<b class="navlabel">Next:</b>
|
||||
<a class="sectref" rel="next" href="module-alsaaudio.html">4 alsaaudio</a>
|
||||
</div>
|
||||
<hr /></div>
|
||||
</div>
|
||||
<!--End of Navigation Panel-->
|
||||
|
||||
<h1><a name="SECTION002300000000000000000">
|
||||
3 Installation</a>
|
||||
</h1>
|
||||
|
||||
<p>
|
||||
Note: the wrappers link with the alsasound library (from the alsa-lib
|
||||
package) and need the ALSA headers for compilation. Verify that you
|
||||
have /usr/lib/libasound.so and /usr/include/alsa (or
|
||||
similar paths) before building.
|
||||
|
||||
<p>
|
||||
On Debian (and probably Ubuntu), make sure you have libasound2-dev installed.
|
||||
|
||||
<p>
|
||||
Naturally you also need to use a kernel with proper ALSA support. This
|
||||
is the default in Linux kernel 2.6 and later. If you are using kernel
|
||||
version 2.4 you may need to install the ALSA patches yourself -
|
||||
although most distributions ship with ALSA kernels.
|
||||
|
||||
<p>
|
||||
To install, execute the following:
|
||||
<br><div class="verbatim"><pre>
|
||||
$ python setup.py build
|
||||
</pre></div>
|
||||
|
||||
<p>
|
||||
And then as root:
|
||||
<br><div class="verbatim"><pre>
|
||||
# python setup.py install
|
||||
</pre></div>
|
||||
|
||||
<p>
|
||||
|
||||
<div class="navigation">
|
||||
<div class='online-navigation'>
|
||||
<p></p><hr />
|
||||
<table align="center" width="100%" cellpadding="0" cellspacing="2">
|
||||
<tr>
|
||||
<td class='online-navigation'><a rel="prev" title="2 alsa and Python"
|
||||
href="node4.html"><img src='previous.png'
|
||||
border='0' height='32' alt='Previous Page' width='32' /></a></td>
|
||||
<td class='online-navigation'><a rel="parent" title="Contents"
|
||||
href="contents.html"><img src='up.png'
|
||||
border='0' height='32' alt='Up one Level' width='32' /></a></td>
|
||||
<td class='online-navigation'><a rel="next" title="4 alsaaudio"
|
||||
href="module-alsaaudio.html"><img src='next.png'
|
||||
border='0' height='32' alt='Next Page' width='32' /></a></td>
|
||||
<td align="center" width="100%">PyAlsaAudio</td>
|
||||
<td class='online-navigation'><a rel="contents" title="Table of Contents"
|
||||
href="contents.html"><img src='contents.png'
|
||||
border='0' height='32' alt='Contents' width='32' /></a></td>
|
||||
<td class='online-navigation'><img src='blank.png'
|
||||
border='0' height='32' alt='' width='32' /></td>
|
||||
<td class='online-navigation'><img src='blank.png'
|
||||
border='0' height='32' alt='' width='32' /></td>
|
||||
</tr></table>
|
||||
<div class='online-navigation'>
|
||||
<b class="navlabel">Previous:</b>
|
||||
<a class="sectref" rel="prev" href="node4.html">2 ALSA and Python</a>
|
||||
<b class="navlabel">Up:</b>
|
||||
<a class="sectref" rel="parent" href="contents.html">Contents</a>
|
||||
<b class="navlabel">Next:</b>
|
||||
<a class="sectref" rel="next" href="module-alsaaudio.html">4 alsaaudio</a>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<span class="release-info">Release 0.4.</span>
|
||||
</div>
|
||||
<!--End of Navigation Panel-->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
-184
@@ -1,184 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<link rel="STYLESHEET" href="pyalsaaudio.css" type='text/css' />
|
||||
<link rel="first" href="pyalsaaudio.html" title='PyAlsaAudio' />
|
||||
<link rel='contents' href='contents.html' title="Contents" />
|
||||
<link rel='last' href='about.html' title='About this document...' />
|
||||
<link rel='help' href='about.html' title='About this document...' />
|
||||
<link rel="next" href="pcm-objects.html" />
|
||||
<link rel="prev" href="module-alsaaudio.html" />
|
||||
<link rel="parent" href="module-alsaaudio.html" />
|
||||
<link rel="next" href="pcm-objects.html" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name='aesop' content='information' />
|
||||
<title>4.1 PCM Terminology and Concepts</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="navigation">
|
||||
<div id='top-navigation-panel' xml:id='top-navigation-panel'>
|
||||
<table align="center" width="100%" cellpadding="0" cellspacing="2">
|
||||
<tr>
|
||||
<td class='online-navigation'><a rel="prev" title="4 alsaaudio"
|
||||
href="module-alsaaudio.html"><img src='previous.png'
|
||||
border='0' height='32' alt='Previous Page' width='32' /></a></td>
|
||||
<td class='online-navigation'><a rel="parent" title="4 alsaaudio"
|
||||
href="module-alsaaudio.html"><img src='up.png'
|
||||
border='0' height='32' alt='Up one Level' width='32' /></a></td>
|
||||
<td class='online-navigation'><a rel="next" title="4.2 pcm Objects"
|
||||
href="pcm-objects.html"><img src='next.png'
|
||||
border='0' height='32' alt='Next Page' width='32' /></a></td>
|
||||
<td align="center" width="100%">PyAlsaAudio</td>
|
||||
<td class='online-navigation'><a rel="contents" title="Table of Contents"
|
||||
href="contents.html"><img src='contents.png'
|
||||
border='0' height='32' alt='Contents' width='32' /></a></td>
|
||||
<td class='online-navigation'><img src='blank.png'
|
||||
border='0' height='32' alt='' width='32' /></td>
|
||||
<td class='online-navigation'><img src='blank.png'
|
||||
border='0' height='32' alt='' width='32' /></td>
|
||||
</tr></table>
|
||||
<div class='online-navigation'>
|
||||
<b class="navlabel">Previous:</b>
|
||||
<a class="sectref" rel="prev" href="module-alsaaudio.html">4 alsaaudio</a>
|
||||
<b class="navlabel">Up:</b>
|
||||
<a class="sectref" rel="parent" href="module-alsaaudio.html">4 alsaaudio</a>
|
||||
<b class="navlabel">Next:</b>
|
||||
<a class="sectref" rel="next" href="pcm-objects.html">4.2 PCM Objects</a>
|
||||
</div>
|
||||
<hr /></div>
|
||||
</div>
|
||||
<!--End of Navigation Panel-->
|
||||
|
||||
<h2><a name="SECTION002410000000000000000">
|
||||
4.1 PCM Terminology and Concepts</a>
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
In order to use PCM devices it is useful to be familiar with some concepts and
|
||||
terminology.
|
||||
|
||||
<p>
|
||||
<dl>
|
||||
<dt><strong>Sample</strong></dt>
|
||||
<dd>PCM audio, whether it is input or output, consists at
|
||||
the lowest level of a number of single samples. A sample represents
|
||||
the sound in a single channel in a brief interval. If more than one
|
||||
channel is in use, more than one sample is required for each
|
||||
interval to describe the sound. Samples can be of many different
|
||||
sizes, ranging from 8 bit to 64 bit presition. The specific format
|
||||
of each sample can also vary - they can be big endian byte order,
|
||||
little endian byte order, or even floats.
|
||||
|
||||
<p>
|
||||
</dd>
|
||||
<dt><strong>Frame</strong></dt>
|
||||
<dd>A frame consists of exactly one sample per channel. If
|
||||
there is only one channel (Mono sound) a frame is simply a single
|
||||
sample. If the sound is stereo, each frame consists of two samples,
|
||||
etc.
|
||||
|
||||
<p>
|
||||
</dd>
|
||||
<dt><strong>Frame size</strong></dt>
|
||||
<dd>This is the size in bytes of each frame. This can
|
||||
vary a lot: if each sample is 8 bits, and we're handling mono sound,
|
||||
the frame size is one byte. Similarly in 6 channel audio with 64 bit
|
||||
floating point samples, the frame size is 48 bytes
|
||||
|
||||
<p>
|
||||
</dd>
|
||||
<dt><strong>Rate</strong></dt>
|
||||
<dd>PCM sound consists of a flow of sound frames. The sound
|
||||
rate controls how often the current frame is replaced. For example,
|
||||
a rate of 8000 Hz means that a new frame is played or captured 8000
|
||||
times per second.
|
||||
|
||||
<p>
|
||||
</dd>
|
||||
<dt><strong>Data rate</strong></dt>
|
||||
<dd>This is the number of bytes, which must be recorded
|
||||
or provided per second at a certain frame size and rate.
|
||||
|
||||
<p>
|
||||
8000 Hz mono sound with 8 bit (1 byte) samples has a data rate of
|
||||
8000 * 1 * 1 = 8 kb/s
|
||||
|
||||
<p>
|
||||
At the other end of the scale, 96000 Hz, 6 channel sound with 64 bit
|
||||
(8 bytes) samples has a data rate of 96000 * 6 * 8 = 4608 kb/s
|
||||
(almost 5 Mb sound data per second)
|
||||
|
||||
<p>
|
||||
</dd>
|
||||
<dt><strong>Period</strong></dt>
|
||||
<dd>When the hardware processes data this is done in chunks
|
||||
of frames. The time interval between each processing (A/D or D/A
|
||||
conversion) is known as the period. The size of the period has
|
||||
direct implication on the latency of the sound input or output. For
|
||||
low-latency the period size should be very small, while low CPU
|
||||
resource usage would usually demand larger period sizes. With ALSA,
|
||||
the CPU utilization is not impacted much by the period size, since
|
||||
the kernel layer buffers multiple periods internally, so each period
|
||||
generates an interrupt and a memory copy, but userspace can be
|
||||
slower and read or write multiple periods at the same time.
|
||||
|
||||
<p>
|
||||
</dd>
|
||||
<dt><strong>Period size</strong></dt>
|
||||
<dd>This is the size of each period in Hz. <em>Not
|
||||
bytes, but Hz!.</em> In <tt class="module">alsaaudio</tt> the period size is set
|
||||
directly, and it is therefore important to understand the
|
||||
significance of this number. If the period size is configured to for
|
||||
example 32, each write should contain exactly 32 frames of sound
|
||||
data, and each read will return either 32 frames of data or nothing
|
||||
at all.
|
||||
|
||||
<p>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
Once you understand these concepts, you will be ready to use the PCM
|
||||
API. Read on.
|
||||
|
||||
<p>
|
||||
|
||||
<div class="navigation">
|
||||
<div class='online-navigation'>
|
||||
<p></p><hr />
|
||||
<table align="center" width="100%" cellpadding="0" cellspacing="2">
|
||||
<tr>
|
||||
<td class='online-navigation'><a rel="prev" title="4 alsaaudio"
|
||||
href="module-alsaaudio.html"><img src='previous.png'
|
||||
border='0' height='32' alt='Previous Page' width='32' /></a></td>
|
||||
<td class='online-navigation'><a rel="parent" title="4 alsaaudio"
|
||||
href="module-alsaaudio.html"><img src='up.png'
|
||||
border='0' height='32' alt='Up one Level' width='32' /></a></td>
|
||||
<td class='online-navigation'><a rel="next" title="4.2 pcm Objects"
|
||||
href="pcm-objects.html"><img src='next.png'
|
||||
border='0' height='32' alt='Next Page' width='32' /></a></td>
|
||||
<td align="center" width="100%">PyAlsaAudio</td>
|
||||
<td class='online-navigation'><a rel="contents" title="Table of Contents"
|
||||
href="contents.html"><img src='contents.png'
|
||||
border='0' height='32' alt='Contents' width='32' /></a></td>
|
||||
<td class='online-navigation'><img src='blank.png'
|
||||
border='0' height='32' alt='' width='32' /></td>
|
||||
<td class='online-navigation'><img src='blank.png'
|
||||
border='0' height='32' alt='' width='32' /></td>
|
||||
</tr></table>
|
||||
<div class='online-navigation'>
|
||||
<b class="navlabel">Previous:</b>
|
||||
<a class="sectref" rel="prev" href="module-alsaaudio.html">4 alsaaudio</a>
|
||||
<b class="navlabel">Up:</b>
|
||||
<a class="sectref" rel="parent" href="module-alsaaudio.html">4 alsaaudio</a>
|
||||
<b class="navlabel">Next:</b>
|
||||
<a class="sectref" rel="next" href="pcm-objects.html">4.2 PCM Objects</a>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<span class="release-info">Release 0.4.</span>
|
||||
</div>
|
||||
<!--End of Navigation Panel-->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,101 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<link rel="STYLESHEET" href="pyalsaaudio.css" type='text/css' />
|
||||
<link rel="first" href="pyalsaaudio.html" title='PyAlsaAudio' />
|
||||
<link rel='contents' href='contents.html' title="Contents" />
|
||||
<link rel='last' href='about.html' title='About this document...' />
|
||||
<link rel='help' href='about.html' title='About this document...' />
|
||||
<link rel="prev" href="mixer-objects.html" />
|
||||
<link rel="parent" href="module-alsaaudio.html" />
|
||||
<link rel="next" href="about.html" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name='aesop' content='information' />
|
||||
<title>4.4 ALSA Examples </title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="navigation">
|
||||
<div id='top-navigation-panel' xml:id='top-navigation-panel'>
|
||||
<table align="center" width="100%" cellpadding="0" cellspacing="2">
|
||||
<tr>
|
||||
<td class='online-navigation'><a rel="prev" title="4.3 mixer Objects"
|
||||
href="mixer-objects.html"><img src='previous.png'
|
||||
border='0' height='32' alt='Previous Page' width='32' /></a></td>
|
||||
<td class='online-navigation'><a rel="parent" title="4 alsaaudio"
|
||||
href="module-alsaaudio.html"><img src='up.png'
|
||||
border='0' height='32' alt='Up one Level' width='32' /></a></td>
|
||||
<td class='online-navigation'><a rel="next" title="About this document ..."
|
||||
href="about.html"><img src='next.png'
|
||||
border='0' height='32' alt='Next Page' width='32' /></a></td>
|
||||
<td align="center" width="100%">PyAlsaAudio</td>
|
||||
<td class='online-navigation'><a rel="contents" title="Table of Contents"
|
||||
href="contents.html"><img src='contents.png'
|
||||
border='0' height='32' alt='Contents' width='32' /></a></td>
|
||||
<td class='online-navigation'><img src='blank.png'
|
||||
border='0' height='32' alt='' width='32' /></td>
|
||||
<td class='online-navigation'><img src='blank.png'
|
||||
border='0' height='32' alt='' width='32' /></td>
|
||||
</tr></table>
|
||||
<div class='online-navigation'>
|
||||
<b class="navlabel">Previous:</b>
|
||||
<a class="sectref" rel="prev" href="mixer-objects.html">4.3 Mixer Objects</a>
|
||||
<b class="navlabel">Up:</b>
|
||||
<a class="sectref" rel="parent" href="module-alsaaudio.html">4 alsaaudio</a>
|
||||
<b class="navlabel">Next:</b>
|
||||
<a class="sectref" rel="next" href="about.html">About this document ...</a>
|
||||
</div>
|
||||
<hr /></div>
|
||||
</div>
|
||||
<!--End of Navigation Panel-->
|
||||
|
||||
<h2><a name="SECTION002440000000000000000"></a><a name="pcm-example"></a>
|
||||
<br>
|
||||
4.4 ALSA Examples
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
For now, the only examples available are the 'playbacktest.py' and the
|
||||
'recordtest.py' programs included. This will change in a future
|
||||
version.
|
||||
|
||||
<p>
|
||||
|
||||
<div class="navigation">
|
||||
<div class='online-navigation'>
|
||||
<p></p><hr />
|
||||
<table align="center" width="100%" cellpadding="0" cellspacing="2">
|
||||
<tr>
|
||||
<td class='online-navigation'><a rel="prev" title="4.3 mixer Objects"
|
||||
href="mixer-objects.html"><img src='previous.png'
|
||||
border='0' height='32' alt='Previous Page' width='32' /></a></td>
|
||||
<td class='online-navigation'><a rel="parent" title="4 alsaaudio"
|
||||
href="module-alsaaudio.html"><img src='up.png'
|
||||
border='0' height='32' alt='Up one Level' width='32' /></a></td>
|
||||
<td class='online-navigation'><a rel="next" title="About this document ..."
|
||||
href="about.html"><img src='next.png'
|
||||
border='0' height='32' alt='Next Page' width='32' /></a></td>
|
||||
<td align="center" width="100%">PyAlsaAudio</td>
|
||||
<td class='online-navigation'><a rel="contents" title="Table of Contents"
|
||||
href="contents.html"><img src='contents.png'
|
||||
border='0' height='32' alt='Contents' width='32' /></a></td>
|
||||
<td class='online-navigation'><img src='blank.png'
|
||||
border='0' height='32' alt='' width='32' /></td>
|
||||
<td class='online-navigation'><img src='blank.png'
|
||||
border='0' height='32' alt='' width='32' /></td>
|
||||
</tr></table>
|
||||
<div class='online-navigation'>
|
||||
<b class="navlabel">Previous:</b>
|
||||
<a class="sectref" rel="prev" href="mixer-objects.html">4.3 Mixer Objects</a>
|
||||
<b class="navlabel">Up:</b>
|
||||
<a class="sectref" rel="parent" href="module-alsaaudio.html">4 alsaaudio</a>
|
||||
<b class="navlabel">Next:</b>
|
||||
<a class="sectref" rel="next" href="about.html">About this document ...</a>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<span class="release-info">Release 0.4.</span>
|
||||
</div>
|
||||
<!--End of Navigation Panel-->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,379 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<link rel="STYLESHEET" href="pyalsaaudio.css" type='text/css' />
|
||||
<link rel="first" href="pyalsaaudio.html" title='PyAlsaAudio' />
|
||||
<link rel='contents' href='contents.html' title="Contents" />
|
||||
<link rel='last' href='about.html' title='About this document...' />
|
||||
<link rel='help' href='about.html' title='About this document...' />
|
||||
<link rel="next" href="mixer-objects.html" />
|
||||
<link rel="prev" href="node7.html" />
|
||||
<link rel="parent" href="module-alsaaudio.html" />
|
||||
<link rel="next" href="mixer-objects.html" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name='aesop' content='information' />
|
||||
<title>4.2 PCM Objects</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="navigation">
|
||||
<div id='top-navigation-panel' xml:id='top-navigation-panel'>
|
||||
<table align="center" width="100%" cellpadding="0" cellspacing="2">
|
||||
<tr>
|
||||
<td class='online-navigation'><a rel="prev" title="4.1 pcm Terminology and"
|
||||
href="node7.html"><img src='previous.png'
|
||||
border='0' height='32' alt='Previous Page' width='32' /></a></td>
|
||||
<td class='online-navigation'><a rel="parent" title="4 alsaaudio"
|
||||
href="module-alsaaudio.html"><img src='up.png'
|
||||
border='0' height='32' alt='Up one Level' width='32' /></a></td>
|
||||
<td class='online-navigation'><a rel="next" title="4.3 mixer Objects"
|
||||
href="mixer-objects.html"><img src='next.png'
|
||||
border='0' height='32' alt='Next Page' width='32' /></a></td>
|
||||
<td align="center" width="100%">PyAlsaAudio</td>
|
||||
<td class='online-navigation'><a rel="contents" title="Table of Contents"
|
||||
href="contents.html"><img src='contents.png'
|
||||
border='0' height='32' alt='Contents' width='32' /></a></td>
|
||||
<td class='online-navigation'><img src='blank.png'
|
||||
border='0' height='32' alt='' width='32' /></td>
|
||||
<td class='online-navigation'><img src='blank.png'
|
||||
border='0' height='32' alt='' width='32' /></td>
|
||||
</tr></table>
|
||||
<div class='online-navigation'>
|
||||
<b class="navlabel">Previous:</b>
|
||||
<a class="sectref" rel="prev" href="node7.html">4.1 PCM Terminology and</a>
|
||||
<b class="navlabel">Up:</b>
|
||||
<a class="sectref" rel="parent" href="module-alsaaudio.html">4 alsaaudio</a>
|
||||
<b class="navlabel">Next:</b>
|
||||
<a class="sectref" rel="next" href="mixer-objects.html">4.3 Mixer Objects</a>
|
||||
</div>
|
||||
<hr /></div>
|
||||
</div>
|
||||
<!--End of Navigation Panel-->
|
||||
|
||||
<h2><a name="SECTION002420000000000000000"></a>
|
||||
<a name="pcm-objects"></a>
|
||||
<br>
|
||||
4.2 PCM Objects
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
The acronym PCM is short for Pulse Code Modulation and is the method
|
||||
used in ALSA and many other places to handle playback and capture of
|
||||
sampled sound data.
|
||||
|
||||
<p>
|
||||
PCM objects in <tt class="module">alsaaudio</tt> are used to do exactly that, either
|
||||
play sample based sound or capture sound from some input source
|
||||
(probably a microphone). The PCM object constructor takes the following
|
||||
arguments:
|
||||
|
||||
<p>
|
||||
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
|
||||
<td><nobr><b><span class="typelabel">class</span> <tt id='l2h-6' xml:id='l2h-6' class="class">PCM</tt></b>(</nobr></td>
|
||||
<td><var></var><big>[</big><var>type</var><big>]</big><var>, </var><big>[</big><var>mode</var><big>]</big><var>, </var><big>[</big><var>cardname</var><big>]</big><var></var>)</td></tr></table></dt>
|
||||
<dd>
|
||||
|
||||
<p>
|
||||
<var>type</var> - can be either PCM_CAPTURE or PCM_PLAYBACK (default).
|
||||
|
||||
<p>
|
||||
<var>mode</var> - can be either PCM_NONBLOCK, PCM_ASYNC, or PCM_NORMAL (the
|
||||
default). In PCM_NONBLOCK mode, calls to read will return immediately
|
||||
independent of wether there is any actual data to read. Similarly,
|
||||
write calls will return immediately without actually writing anything
|
||||
to the playout buffer if the buffer is full.
|
||||
|
||||
<p>
|
||||
In the current version of <tt class="module">alsaaudio</tt> PCM_ASYNC is useless,
|
||||
since it relies on a callback procedure, which can't be specified through
|
||||
this API yet.
|
||||
|
||||
<p>
|
||||
<var>cardname</var> - specifies which card should be used (this is only
|
||||
relevant if you have more than one sound card). Omit to use the
|
||||
default sound card
|
||||
|
||||
<p>
|
||||
This will construct a PCM object with default settings:
|
||||
|
||||
<p>
|
||||
Sample format: PCM_FORMAT_S16_LE
|
||||
<br>
|
||||
Rate: 8000 Hz
|
||||
<br>
|
||||
Channels: 2
|
||||
<br>
|
||||
Period size: 32 frames
|
||||
<br></dl>
|
||||
|
||||
<p>
|
||||
PCM objects have the following methods:
|
||||
|
||||
<p>
|
||||
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
|
||||
<td><nobr><b><tt id='l2h-7' xml:id='l2h-7' class="method">pcmtype</tt></b>(</nobr></td>
|
||||
<td><var></var>)</td></tr></table></dt>
|
||||
<dd>
|
||||
Returns the type of PCM object. Either PCM_CAPTURE or PCM_PLAYBACK.
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
|
||||
<td><nobr><b><tt id='l2h-8' xml:id='l2h-8' class="method">pcmmode</tt></b>(</nobr></td>
|
||||
<td><var></var>)</td></tr></table></dt>
|
||||
<dd>
|
||||
Return the mode of the PCM object. One of PCM_NONBLOCK, PCM_ASYNC,
|
||||
or PCM_NORMAL
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
|
||||
<td><nobr><b><tt id='l2h-9' xml:id='l2h-9' class="method">cardname</tt></b>(</nobr></td>
|
||||
<td><var></var>)</td></tr></table></dt>
|
||||
<dd>
|
||||
Return the name of the sound card used by this PCM object.
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
|
||||
<td><nobr><b><tt id='l2h-10' xml:id='l2h-10' class="method">setchannels</tt></b>(</nobr></td>
|
||||
<td><var>nchannels</var>)</td></tr></table></dt>
|
||||
<dd>
|
||||
Used to set the number of capture or playback channels. Common
|
||||
values are: 1 = mono, 2 = stereo, and 6 = full 6 channel audio. Few
|
||||
sound cards support more than 2 channels
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
|
||||
<td><nobr><b><tt id='l2h-11' xml:id='l2h-11' class="method">setrate</tt></b>(</nobr></td>
|
||||
<td><var>rate</var>)</td></tr></table></dt>
|
||||
<dd>
|
||||
Set the sample rate in Hz for the device. Typical values are 8000
|
||||
(poor sound), 16000, 44100 (cd quality), and 96000
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
|
||||
<td><nobr><b><tt id='l2h-12' xml:id='l2h-12' class="method">setformat</tt></b>(</nobr></td>
|
||||
<td><var>format</var>)</td></tr></table></dt>
|
||||
<dd>
|
||||
The sound <var>format</var> of the device. Sound format controls how the PCM
|
||||
device interpret data for playback, and how data is encoded in
|
||||
captures.
|
||||
|
||||
<p>
|
||||
The following formats are provided by ALSA:
|
||||
<div class="center"><table class="realtable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="left" >Format</th>
|
||||
<th class="left" >Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td class="left" valign="baseline"><formats>PCM_FORMAT_S8</formats></td>
|
||||
<td class="left" >Signed 8 bit samples for each channel</td></tr>
|
||||
<tr><td class="left" valign="baseline"><formats>PCM_FORMAT_U8</formats></td>
|
||||
<td class="left" >Signed 8 bit samples for each channel</td></tr>
|
||||
<tr><td class="left" valign="baseline"><formats>PCM_FORMAT_S16_LE</formats></td>
|
||||
<td class="left" >Signed 16 bit samples for each channel
|
||||
(Little Endian byte order)</td></tr>
|
||||
<tr><td class="left" valign="baseline"><formats>PCM_FORMAT_S16_BE</formats></td>
|
||||
<td class="left" >Signed 16
|
||||
bit samples for each channel (Big Endian byte order)</td></tr>
|
||||
<tr><td class="left" valign="baseline"><formats>PCM_FORMAT_U16_LE</formats></td>
|
||||
<td class="left" >Unsigned 16 bit samples for each channel
|
||||
(Little Endian byte order)</td></tr>
|
||||
<tr><td class="left" valign="baseline"><formats>PCM_FORMAT_U16_BE</formats></td>
|
||||
<td class="left" >Unsigned 16
|
||||
bit samples for each channel (Big Endian byte order)</td></tr>
|
||||
<tr><td class="left" valign="baseline"><formats>PCM_FORMAT_S24_LE</formats></td>
|
||||
<td class="left" >Signed 24 bit samples for each channel
|
||||
(Little Endian byte order)</td></tr>
|
||||
<tr><td class="left" valign="baseline"><formats>PCM_FORMAT_S24_BE</formats></td>
|
||||
<td class="left" >Signed 24
|
||||
bit samples for each channel (Big Endian byte order)</td></tr>
|
||||
<tr><td class="left" valign="baseline"><formats>PCM_FORMAT_U24_LE</formats></td>
|
||||
<td class="left" >Unsigned 24 bit samples for each channel
|
||||
(Little Endian byte order)</td></tr>
|
||||
<tr><td class="left" valign="baseline"><formats>PCM_FORMAT_U24_BE</formats></td>
|
||||
<td class="left" >Unsigned 24
|
||||
bit samples for each channel (Big Endian byte order)</td></tr>
|
||||
<tr><td class="left" valign="baseline"><formats>PCM_FORMAT_S32_LE</formats></td>
|
||||
<td class="left" >Signed 32 bit samples for each channel
|
||||
(Little Endian byte order)</td></tr>
|
||||
<tr><td class="left" valign="baseline"><formats>PCM_FORMAT_S32_BE</formats></td>
|
||||
<td class="left" >Signed 32
|
||||
bit samples for each channel (Big Endian byte order)</td></tr>
|
||||
<tr><td class="left" valign="baseline"><formats>PCM_FORMAT_U32_LE</formats></td>
|
||||
<td class="left" >Unsigned 32 bit samples for each channel
|
||||
(Little Endian byte order)</td></tr>
|
||||
<tr><td class="left" valign="baseline"><formats>PCM_FORMAT_U32_BE</formats></td>
|
||||
<td class="left" >Unsigned 32
|
||||
bit samples for each channel (Big Endian byte order)</td></tr>
|
||||
<tr><td class="left" valign="baseline"><formats>PCM_FORMAT_FLOAT_LE</formats></td>
|
||||
<td class="left" >32 bit samples encoded as float.
|
||||
(Little Endian byte order)</td></tr>
|
||||
<tr><td class="left" valign="baseline"><formats>PCM_FORMAT_FLOAT_BE</formats></td>
|
||||
<td class="left" >32 bit
|
||||
samples encoded as float (Big Endian byte order)</td></tr>
|
||||
<tr><td class="left" valign="baseline"><formats>PCM_FORMAT_FLOAT64_LE</formats></td>
|
||||
<td class="left" >64 bit samples encoded as float.
|
||||
(Little Endian byte order)</td></tr>
|
||||
<tr><td class="left" valign="baseline"><formats>PCM_FORMAT_FLOAT64_BE</formats></td>
|
||||
<td class="left" >64 bit
|
||||
samples encoded as float. (Big Endian byte order)</td></tr>
|
||||
<tr><td class="left" valign="baseline"><formats>PCM_FORMAT_MU_LAW</formats></td>
|
||||
<td class="left" >A logarithmic encoding (used by Sun .au
|
||||
files)</td></tr>
|
||||
<tr><td class="left" valign="baseline"><formats>PCM_FORMAT_A_LAW</formats></td>
|
||||
<td class="left" >Another logarithmic encoding</td></tr>
|
||||
<tr><td class="left" valign="baseline"><formats>PCM_FORMAT_IMA_ADPCM</formats></td>
|
||||
<td class="left" >a 4:1 compressed format defined by the
|
||||
Interactive Multimedia Association</td></tr>
|
||||
<tr><td class="left" valign="baseline"><formats>PCM_FORMAT_MPEG</formats></td>
|
||||
<td class="left" >MPEG
|
||||
encoded audio?</td></tr>
|
||||
<tr><td class="left" valign="baseline"><formats>PCM_FORMAT_GSM</formats></td>
|
||||
<td class="left" >9600 bits/s constant rate encoding for speech</td></tr></tbody>
|
||||
</table></div>
|
||||
|
||||
<p>
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
|
||||
<td><nobr><b><tt id='l2h-13' xml:id='l2h-13' class="method">setperiodsize</tt></b>(</nobr></td>
|
||||
<td><var>period</var>)</td></tr></table></dt>
|
||||
<dd>
|
||||
Sets the actual period size in frames. Each write should consist of
|
||||
exactly this number of frames, and each read will return this number
|
||||
of frames (unless the device is in PCM_NONBLOCK mode, in which case
|
||||
it may return nothing at all)
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
|
||||
<td><nobr><b><tt id='l2h-14' xml:id='l2h-14' class="method">read</tt></b>(</nobr></td>
|
||||
<td><var></var>)</td></tr></table></dt>
|
||||
<dd>
|
||||
In PCM_NORMAL mode, this function blocks until a full period is
|
||||
available, and then returns a tuple (length,data) where
|
||||
<em>length</em> is the number of frames of captured data, and
|
||||
<em>data</em> is the captured sound frames as a string. The length of
|
||||
the returned data will be periodsize*framesize bytes.
|
||||
|
||||
<p>
|
||||
In PCM_NONBLOCK mode, the call will not block, but will return
|
||||
<code>(0,'')</code> if no new period has become available since the last
|
||||
call to read.
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
|
||||
<td><nobr><b><tt id='l2h-15' xml:id='l2h-15' class="method">write</tt></b>(</nobr></td>
|
||||
<td><var>data</var>)</td></tr></table></dt>
|
||||
<dd>
|
||||
Writes (plays) the sound in data. The length of data <em>must</em> be
|
||||
a multiple of the frame size, and <em>should</em> be exactly the size
|
||||
of a period. If less than 'period size' frames are provided, the
|
||||
actual playout will not happen until more data is written.
|
||||
|
||||
<p>
|
||||
If the device is not in PCM_NONBLOCK mode, this call will block if
|
||||
the kernel buffer is full, and until enough sound has been played to
|
||||
allow the sound data to be buffered. The call always returns the
|
||||
size of the data provided
|
||||
|
||||
<p>
|
||||
In PCM_NONBLOCK mode, the call will return immediately, with a
|
||||
return value of zero, if the buffer is full. In this case, the data
|
||||
should be written at a later time.
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
|
||||
<td><nobr><b><tt id='l2h-16' xml:id='l2h-16' class="method">pause</tt></b>(</nobr></td>
|
||||
<td><var></var><big>[</big><var>enable=1</var><big>]</big><var></var>)</td></tr></table></dt>
|
||||
<dd>
|
||||
If <var>enable</var> is 1, playback or capture is paused. If <var>enable</var> is 0,
|
||||
playback/capture is resumed.
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
<strong>A few hints on using PCM devices for playback</strong>
|
||||
|
||||
<p>
|
||||
The most common reason for problems with playback of PCM audio, is
|
||||
that the people don't properly understand that writes to PCM devices
|
||||
must match <em>exactly</em> the data rate of the device.
|
||||
|
||||
<p>
|
||||
If too little data is written to the device, it will underrun, and
|
||||
ugly clicking sounds will occur. Conversely, of too much data is
|
||||
written to the device, the write function will either block
|
||||
(PCM_NORMAL mode) or return zero (PCM_NONBLOCK mode).
|
||||
|
||||
<p>
|
||||
If your program does nothing, but play sound, the easiest way is to
|
||||
put the device in PCM_NORMAL mode, and just write as much data to the
|
||||
device as possible. This strategy can also be achieved by using a
|
||||
separate thread with the sole task of playing out sound.
|
||||
|
||||
<p>
|
||||
In GUI programs, however, it may be a better strategy to setup the
|
||||
device, preload the buffer with a few periods by calling write a
|
||||
couple of times, and then use some timer method to write one period
|
||||
size of data to the device every period. The purpose of the preloading
|
||||
is to avoid underrun clicks if the used timer doesn't expire exactly
|
||||
on time.
|
||||
|
||||
<p>
|
||||
Also note, that most timer APIs that you can find for Python will
|
||||
cummulate time delays: If you set the timer to expire after 1/10'th of
|
||||
a second, the actual timeout will happen slightly later, which will
|
||||
accumulate to quite a lot after a few seconds. Hint: use time.time()
|
||||
to check how much time has really passed, and add extra writes as
|
||||
nessecary.
|
||||
|
||||
<p>
|
||||
|
||||
<div class="navigation">
|
||||
<div class='online-navigation'>
|
||||
<p></p><hr />
|
||||
<table align="center" width="100%" cellpadding="0" cellspacing="2">
|
||||
<tr>
|
||||
<td class='online-navigation'><a rel="prev" title="4.1 pcm Terminology and"
|
||||
href="node7.html"><img src='previous.png'
|
||||
border='0' height='32' alt='Previous Page' width='32' /></a></td>
|
||||
<td class='online-navigation'><a rel="parent" title="4 alsaaudio"
|
||||
href="module-alsaaudio.html"><img src='up.png'
|
||||
border='0' height='32' alt='Up one Level' width='32' /></a></td>
|
||||
<td class='online-navigation'><a rel="next" title="4.3 mixer Objects"
|
||||
href="mixer-objects.html"><img src='next.png'
|
||||
border='0' height='32' alt='Next Page' width='32' /></a></td>
|
||||
<td align="center" width="100%">PyAlsaAudio</td>
|
||||
<td class='online-navigation'><a rel="contents" title="Table of Contents"
|
||||
href="contents.html"><img src='contents.png'
|
||||
border='0' height='32' alt='Contents' width='32' /></a></td>
|
||||
<td class='online-navigation'><img src='blank.png'
|
||||
border='0' height='32' alt='' width='32' /></td>
|
||||
<td class='online-navigation'><img src='blank.png'
|
||||
border='0' height='32' alt='' width='32' /></td>
|
||||
</tr></table>
|
||||
<div class='online-navigation'>
|
||||
<b class="navlabel">Previous:</b>
|
||||
<a class="sectref" rel="prev" href="node7.html">4.1 PCM Terminology and</a>
|
||||
<b class="navlabel">Up:</b>
|
||||
<a class="sectref" rel="parent" href="module-alsaaudio.html">4 alsaaudio</a>
|
||||
<b class="navlabel">Next:</b>
|
||||
<a class="sectref" rel="next" href="mixer-objects.html">4.3 Mixer Objects</a>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<span class="release-info">Release 0.4.</span>
|
||||
</div>
|
||||
<!--End of Navigation Panel-->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,111 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<link rel="STYLESHEET" href="pyalsaaudio.css" type='text/css' />
|
||||
<link rel="first" href="pyalsaaudio.html" title='PyAlsaAudio' />
|
||||
<link rel='contents' href='contents.html' title="Contents" />
|
||||
<link rel='last' href='about.html' title='About this document...' />
|
||||
<link rel='help' href='about.html' title='About this document...' />
|
||||
<link rel="next" href="front.html" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name='aesop' content='information' />
|
||||
<title>PyAlsaAudio</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="navigation">
|
||||
<div id='top-navigation-panel' xml:id='top-navigation-panel'>
|
||||
<table align="center" width="100%" cellpadding="0" cellspacing="2">
|
||||
<tr>
|
||||
<td class='online-navigation'><img src='previous.png'
|
||||
border='0' height='32' alt='Previous Page' width='32' /></td>
|
||||
<td class='online-navigation'><img src='up.png'
|
||||
border='0' height='32' alt='Up one Level' width='32' /></td>
|
||||
<td class='online-navigation'><a rel="next" title="Front Matter"
|
||||
href="front.html"><img src='next.png'
|
||||
border='0' height='32' alt='Next Page' width='32' /></a></td>
|
||||
<td align="center" width="100%">PyAlsaAudio</td>
|
||||
<td class='online-navigation'><a rel="contents" title="Table of Contents"
|
||||
href="contents.html"><img src='contents.png'
|
||||
border='0' height='32' alt='Contents' width='32' /></a></td>
|
||||
<td class='online-navigation'><img src='blank.png'
|
||||
border='0' height='32' alt='' width='32' /></td>
|
||||
<td class='online-navigation'><img src='blank.png'
|
||||
border='0' height='32' alt='' width='32' /></td>
|
||||
</tr></table>
|
||||
<div class='online-navigation'>
|
||||
<b class="navlabel">Next:</b>
|
||||
<a class="sectref" rel="next" href="front.html">Front Matter</a>
|
||||
</div>
|
||||
<hr /></div>
|
||||
</div>
|
||||
<!--End of Navigation Panel-->
|
||||
|
||||
<div class="titlepage">
|
||||
<div class='center'>
|
||||
<h1>PyAlsaAudio</h1>
|
||||
<p><b><font size="+2">Casper Wilstrup</font></b></p>
|
||||
<p>cwi@aves.dk</p>
|
||||
<p></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
|
||||
<p><br /></p><hr class='online-navigation' />
|
||||
<div class='online-navigation'>
|
||||
<!--Table of Child-Links-->
|
||||
<a name="CHILD_LINKS"></a>
|
||||
|
||||
<ul class="ChildLinks">
|
||||
<li><a href="front.html">Front Matter</a>
|
||||
<li><a href="contents.html">Contents</a>
|
||||
<ul>
|
||||
<li><a href="node3.html">1 What is ALSA</a>
|
||||
<li><a href="node4.html">2 ALSA and Python</a>
|
||||
<li><a href="node5.html">3 Installation</a>
|
||||
<li><a href="module-alsaaudio.html">4 <tt class="module">alsaaudio</tt></a>
|
||||
<ul>
|
||||
<li><a href="node7.html">4.1 PCM Terminology and Concepts</a>
|
||||
<li><a href="pcm-objects.html">4.2 PCM Objects</a>
|
||||
<li><a href="mixer-objects.html">4.3 Mixer Objects</a>
|
||||
<li><a href="pcm-example.html">4.4 ALSA Examples</a>
|
||||
</ul>
|
||||
</ul>
|
||||
<li><a href="about.html">About this document ...</a>
|
||||
</ul>
|
||||
<!--End of Table of Child-Links-->
|
||||
</div>
|
||||
|
||||
<div class="navigation">
|
||||
<div class='online-navigation'>
|
||||
<p></p><hr />
|
||||
<table align="center" width="100%" cellpadding="0" cellspacing="2">
|
||||
<tr>
|
||||
<td class='online-navigation'><img src='previous.png'
|
||||
border='0' height='32' alt='Previous Page' width='32' /></td>
|
||||
<td class='online-navigation'><img src='up.png'
|
||||
border='0' height='32' alt='Up one Level' width='32' /></td>
|
||||
<td class='online-navigation'><a rel="next" title="Front Matter"
|
||||
href="front.html"><img src='next.png'
|
||||
border='0' height='32' alt='Next Page' width='32' /></a></td>
|
||||
<td align="center" width="100%">PyAlsaAudio</td>
|
||||
<td class='online-navigation'><a rel="contents" title="Table of Contents"
|
||||
href="contents.html"><img src='contents.png'
|
||||
border='0' height='32' alt='Contents' width='32' /></a></td>
|
||||
<td class='online-navigation'><img src='blank.png'
|
||||
border='0' height='32' alt='' width='32' /></td>
|
||||
<td class='online-navigation'><img src='blank.png'
|
||||
border='0' height='32' alt='' width='32' /></td>
|
||||
</tr></table>
|
||||
<div class='online-navigation'>
|
||||
<b class="navlabel">Next:</b>
|
||||
<a class="sectref" rel="next" href="front.html">Front Matter</a>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<span class="release-info">Release 0.4.</span>
|
||||
</div>
|
||||
<!--End of Navigation Panel-->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
+31
-4
@@ -1,6 +1,6 @@
|
||||
***************
|
||||
PyAlsaAudio
|
||||
***************
|
||||
************
|
||||
Introduction
|
||||
************
|
||||
|
||||
:Author: Casper Wilstrup
|
||||
:Author: Lars Immisch
|
||||
@@ -91,7 +91,7 @@ Note: the wrappers link with the alsasound library (from the alsa-lib package)
|
||||
and need the ALSA headers for compilation. Verify that you have
|
||||
/usr/lib/libasound.so and /usr/include/alsa (or similar paths) before building.
|
||||
|
||||
On Debian (and probably Ubuntu), make sure you have libasound2-dev installed.
|
||||
*On Debian (and probably Ubuntu), install libasound2-dev.*
|
||||
|
||||
Naturally you also need to use a kernel with proper ALSA support. This is the
|
||||
default in Linux kernel 2.6 and later. If you are using kernel version 2.4 you
|
||||
@@ -105,3 +105,30 @@ To install, execute the following: --- ::
|
||||
And then as root: --- ::
|
||||
|
||||
# python setup.py install
|
||||
|
||||
*******
|
||||
Testing
|
||||
*******
|
||||
|
||||
First of all, run::
|
||||
|
||||
$ python test.py
|
||||
|
||||
This is a small test suite that mostly performs consistency tests. If
|
||||
it fails, please file a `bug report
|
||||
<http://sourceforge.net/tracker/?group_id=120651>`_.
|
||||
|
||||
To test PCM recordings (on your default soundcard), verify your
|
||||
microphone works, then do::
|
||||
|
||||
$ python recordtest.py <filename>
|
||||
|
||||
Speak into the microphone, and interrupt the recording at any time
|
||||
with ``Ctl-C``.
|
||||
|
||||
Play back the recording with::
|
||||
|
||||
$ python playbacktest.py <filename>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
****************************
|
||||
PCM Terminology and Concepts
|
||||
****************************
|
||||
|
||||
In order to use PCM devices it is useful to be familiar with some concepts and
|
||||
terminology.
|
||||
|
||||
Sample
|
||||
PCM audio, whether it is input or output, consists of *samples*.
|
||||
A single sample represents the amplitude of one channel of sound
|
||||
at a certain point in time. A lot of individual samples are
|
||||
necessary to represent actual sound; for CD audio, 44100 samples
|
||||
are taken every second.
|
||||
|
||||
Samples can be of many different sizes, ranging from 8 bit to 64
|
||||
bit precision. The specific format of each sample can also vary -
|
||||
they can be big endian byte integers, little endian byte integers, or
|
||||
floating point numbers.
|
||||
|
||||
Musically, the sample size determines the dynamic range. The
|
||||
dynamic range is the difference between the quietest and the
|
||||
loudest signal that can be resproduced.
|
||||
|
||||
Frame
|
||||
A frame consists of exactly one sample per channel. If there is only one
|
||||
channel (Mono sound) a frame is simply a single sample. If the sound is
|
||||
stereo, each frame consists of two samples, etc.
|
||||
|
||||
Frame size
|
||||
This is the size in bytes of each frame. This can vary a lot: if each sample
|
||||
is 8 bits, and we're handling mono sound, the frame size is one byte.
|
||||
Similarly in 6 channel audio with 64 bit floating point samples, the frame
|
||||
size is 48 bytes
|
||||
|
||||
Rate
|
||||
PCM sound consists of a flow of sound frames. The sound rate controls how
|
||||
often the current frame is replaced. For example, a rate of 8000 Hz
|
||||
means that a new frame is played or captured 8000 times per second.
|
||||
|
||||
Data rate
|
||||
This is the number of bytes, which must be recorded or provided per
|
||||
second at a certain frame size and rate.
|
||||
|
||||
8000 Hz mono sound with 8 bit (1 byte) samples has a data rate of
|
||||
8000 \* 1 \* 1 = 8 kb/s or 64kbit/s. This is typically used for telephony.
|
||||
|
||||
At the other end of the scale, 96000 Hz, 6 channel sound with 64
|
||||
bit (8 bytes) samples has a data rate of 96000 \* 6 \* 8 = 4608
|
||||
kb/s (almost 5 Mb sound data per second)
|
||||
|
||||
Period
|
||||
When the hardware processes data this is done in chunks of frames. The time
|
||||
interval between each processing (A/D or D/A conversion) is known
|
||||
as the period.
|
||||
The size of the period has direct implication on the latency of the
|
||||
sound input or output. For low-latency the period size should be
|
||||
very small, while low CPU resource usage would usually demand
|
||||
larger period sizes. With ALSA, the CPU utilization is not impacted
|
||||
much by the period size, since the kernel layer buffers multiple
|
||||
periods internally, so each period generates an interrupt and a
|
||||
memory copy, but userspace can be slower and read or write multiple
|
||||
periods at the same time.
|
||||
|
||||
Period size
|
||||
This is the size of each period in Hz. *Not bytes, but Hz!.* In
|
||||
:mod:`alsaaudio` the period size is set directly, and it is
|
||||
therefore important to understand the significance of this
|
||||
number. If the period size is configured to for example 32,
|
||||
each write should contain exactly 32 frames of sound data, and each
|
||||
read will return either 32 frames of data or nothing at all.
|
||||
|
||||
Once you understand these concepts, you will be ready to use the PCM API. Read
|
||||
on.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user