Browse Source

PyRtAudio: Update to Python 3

Fixes #199.
master
Stephen Sinclair 6 years ago
parent
commit
ba984d90fa
3 changed files with 180 additions and 79 deletions
  1. +71
    -70
      contrib/python/pyrtaudio/PyRtAudioTest.py
  2. +109
    -8
      contrib/python/pyrtaudio/rtaudiomodule.cpp
  3. +0
    -1
      contrib/python/pyrtaudio/setup.py

+ 71
- 70
contrib/python/pyrtaudio/PyRtAudioTest.py View File

@@ -1,70 +1,71 @@
import rtaudio as rt
from math import cos
import struct
class audio_generator:
def __init__(self):
self.idx = -1
self.freq = 440.
def __call__(self):
self.idx += 1
if self.idx%48000 == 0:
self.freq *= 2**(1/12.)
return 0.5*cos(2.*3.1416*self.freq*self.idx/48000.)
class callback:
def __init__(self, gen):
self.gen = gen
self.i = 0
def __call__(self,playback, capture):
[struct.pack_into("f", playback, 4*o, self.gen()) for o in xrange(256)]
self.i = self.i + 256
if self.i > 48000*10:
print '.'
return 1
dac = rt.RtAudio()
n = dac.getDeviceCount()
print 'Number of devices available: ', n
for i in range(n):
try:
print dac.getDeviceInfo(i)
except rt.RtError as e:
print e
print 'Default output device: ', dac.getDefaultOutputDevice()
print 'Default input device: ', dac.getDefaultInputDevice()
print 'is stream open: ', dac.isStreamOpen()
print 'is stream running: ', dac.isStreamRunning()
oParams = {'deviceId': 1, 'nChannels': 1, 'firstChannel': 0}
iParams = {'deviceId': 1, 'nChannels': 1, 'firstChannel': 0}
try:
dac.openStream(oParams,oParams,48000,256,callback(audio_generator()) )
except rt.RtError as e:
print e
else:
dac.startStream()
import time
print 'latency: ', dac.getStreamLatency()
while (dac.isStreamRunning()):
time.sleep(0.1)
print dac.getStreamTime()
dac.stopStream()
dac.abortStream()
dac.closeStream()

from __future__ import print_function
import threading
import rtaudio as rt

from math import cos

import struct


class audio_generator:
def __init__(self):
self.idx = -1
self.freq = 440.
def __call__(self):
self.idx += 1
if self.idx%48000 == 0:
self.freq *= 2**(1/12.)
return 0.5*cos(2.*3.1416*self.freq*self.idx/48000.)


class callback:
def __init__(self, gen):
self.gen = gen
self.i = 0
def __call__(self,playback, capture):
[struct.pack_into("f", playback, 4*o, self.gen()) for o in range(256)]
self.i = self.i + 256
if self.i > 48000*10:
print('.')
return 1

dac = rt.RtAudio()

n = dac.getDeviceCount()
print('Number of devices available: ', n)

for i in range(n):
try:
print(dac.getDeviceInfo(i))
except rt.RtError as e:
print(e)


print('Default output device: ', dac.getDefaultOutputDevice())
print('Default input device: ', dac.getDefaultInputDevice())

print('is stream open: ', dac.isStreamOpen())
print('is stream running: ', dac.isStreamRunning())

oParams = {'deviceId': 0, 'nChannels': 1, 'firstChannel': 0}
iParams = {'deviceId': 0, 'nChannels': 1, 'firstChannel': 0}

try:
dac.openStream(oParams,oParams,48000,256,callback(audio_generator()) )
except rt.RtError as e:
print(e)
else:
dac.startStream()

import time
print('latency: ', dac.getStreamLatency())

while (dac.isStreamRunning()):
time.sleep(0.1)

print(dac.getStreamTime())

dac.stopStream()
dac.abortStream()
dac.closeStream()

+ 109
- 8
contrib/python/pyrtaudio/rtaudiomodule.cpp View File

@@ -70,8 +70,13 @@ extern "C" {
if (py_callback_func) {
PyGILState_STATE gstate = PyGILState_Ensure();

#if PY_MAJOR_VERSION >= 3
PyObject* iBuffer = PyMemoryView_FromMemory((char*)in, sizeof(float) * self->inputChannels * nBufferFrames, PyBUF_READ);
PyObject* oBuffer = PyMemoryView_FromMemory((char*)out, sizeof(float) * nBufferFrames, PyBUF_WRITE);
#else
PyObject* iBuffer = PyBuffer_FromMemory(in, sizeof(float) * self->inputChannels * nBufferFrames);
PyObject* oBuffer = PyBuffer_FromReadWriteMemory(out, sizeof(float) * nBufferFrames);
#endif
PyObject *arglist = Py_BuildValue("(O,O)", oBuffer, iBuffer);

if (arglist == NULL) {
@@ -87,9 +92,17 @@ extern "C" {
if (PyErr_Occurred() != NULL) {
PyErr_Print();
}
else if PyInt_Check(result) {
#if PY_MAJOR_VERSION >= 3
else if (result == NULL)
retval = 0;
else if (PyLong_Check(result)) {
retval = PyLong_AsLong(result);
}
#else
else if (PyInt_Check(result)) {
retval = PyInt_AsLong(result);
}
#endif
Py_DECREF(arglist);
Py_DECREF(oBuffer);
@@ -115,7 +128,7 @@ extern "C" {
delete self->dac;
}

self->ob_type->tp_free((PyObject *) self);
Py_TYPE(self)->tp_free((PyObject *) self);
}


@@ -196,6 +209,20 @@ extern "C" {
oParams.firstChannel = 0;

if (PyDict_Check(oParamsObj)) {
#if PY_MAJOR_VERSION >= 3
if (PyDict_Contains(oParamsObj, PyUnicode_FromString("deviceId"))) {
PyObject *value = PyDict_GetItem(oParamsObj, PyUnicode_FromString("deviceId"));
oParams.deviceId = PyLong_AsLong(value);
}
if (PyDict_Contains(oParamsObj, PyUnicode_FromString("nChannels"))) {
PyObject *value = PyDict_GetItem(oParamsObj, PyUnicode_FromString("nChannels"));
oParams.nChannels = PyLong_AsLong(value);
}
if (PyDict_Contains(oParamsObj, PyUnicode_FromString("firstChannel"))) {
PyObject *value = PyDict_GetItem(oParamsObj, PyUnicode_FromString("firstChannel"));
oParams.firstChannel = PyLong_AsLong(value);
}
#else
if (PyDict_Contains(oParamsObj, PyString_FromString("deviceId"))) {
PyObject *value = PyDict_GetItem(oParamsObj, PyString_FromString("deviceId"));
oParams.deviceId = PyInt_AsLong(value);
@@ -208,6 +235,7 @@ extern "C" {
PyObject *value = PyDict_GetItem(oParamsObj, PyString_FromString("firstChannel"));
oParams.firstChannel = PyInt_AsLong(value);
}
#endif
}
else {
printf("First argument must be a dictionary. Default values will be used.\n");
@@ -219,6 +247,20 @@ extern "C" {
iParams.firstChannel = 0;

if (PyDict_Check(iParamsObj)) {
#if PY_MAJOR_VERSION >= 3
if (PyDict_Contains(iParamsObj, PyUnicode_FromString("deviceId"))) {
PyObject *value = PyDict_GetItem(iParamsObj, PyUnicode_FromString("deviceId"));
iParams.deviceId = PyLong_AsLong(value);
}
if (PyDict_Contains(iParamsObj, PyUnicode_FromString("nChannels"))) {
PyObject *value = PyDict_GetItem(iParamsObj, PyUnicode_FromString("nChannels"));
iParams.nChannels = PyLong_AsLong(value);
}
if (PyDict_Contains(iParamsObj, PyUnicode_FromString("firstChannel"))) {
PyObject *value = PyDict_GetItem(iParamsObj, PyUnicode_FromString("firstChannel"));
iParams.firstChannel = PyLong_AsLong(value);
}
#else
if (PyDict_Contains(iParamsObj, PyString_FromString("deviceId"))) {
PyObject *value = PyDict_GetItem(iParamsObj, PyString_FromString("deviceId"));
iParams.deviceId = PyInt_AsLong(value);
@@ -231,6 +273,7 @@ extern "C" {
PyObject *value = PyDict_GetItem(iParamsObj, PyString_FromString("firstChannel"));
iParams.firstChannel = PyInt_AsLong(value);
}
#endif
}
else {
printf("Second argument must be a dictionary. Default values will be used.\n");
@@ -371,7 +414,11 @@ extern "C" {
{
if (self == NULL || self->dac == NULL) return NULL;

#if PY_MAJOR_VERSION >= 3
return PyLong_FromLong(self->dac->getDeviceCount());
#else
return PyInt_FromLong(self->dac->getDeviceCount());
#endif
}

static PyObject* RtAudio_getDeviceInfo(PyRtAudio *self, PyObject *args)
@@ -397,6 +444,19 @@ extern "C" {
}
PyObject* obj;

#if PY_MAJOR_VERSION >= 3
obj = PyUnicode_FromString(info.name.c_str());
PyDict_SetItemString(info_dict, "name", obj);

obj = PyLong_FromLong(info.outputChannels);
PyDict_SetItemString(info_dict, "outputChannels", obj);

obj = PyLong_FromLong(info.inputChannels);
PyDict_SetItemString(info_dict, "inputChannels", obj);

obj = PyLong_FromLong(info.duplexChannels);
PyDict_SetItemString(info_dict, "duplexChannels", obj);
#else
obj = PyString_FromString(info.name.c_str());
PyDict_SetItemString(info_dict, "name", obj);

@@ -408,6 +468,7 @@ extern "C" {

obj = PyInt_FromLong(info.duplexChannels);
PyDict_SetItemString(info_dict, "duplexChannels", obj);
#endif

if (info.isDefaultOutput) {
Py_INCREF(Py_True);
@@ -440,13 +501,21 @@ extern "C" {
static PyObject* RtAudio_getDefaultOutputDevice(PyRtAudio *self, PyObject *args)
{
if (self == NULL || self->dac == NULL) return NULL;
#if PY_MAJOR_VERSION >= 3
return PyLong_FromLong(self->dac->getDefaultOutputDevice());
#else
return PyInt_FromLong(self->dac->getDefaultOutputDevice());
#endif
}

static PyObject* RtAudio_getDefaultInputDevice(PyRtAudio *self, PyObject *args)
{
if (self == NULL || self->dac == NULL) return NULL;
#if PY_MAJOR_VERSION >= 3
return PyLong_FromLong(self->dac->getDefaultInputDevice());
#else
return PyInt_FromLong(self->dac->getDefaultInputDevice());
#endif
}

static PyObject* RtAudio_getStreamTime(PyRtAudio *self, PyObject *args)
@@ -458,13 +527,21 @@ extern "C" {
static PyObject* RtAudio_getStreamLatency(PyRtAudio *self, PyObject *args)
{
if (self == NULL || self->dac == NULL) return NULL;
#if PY_MAJOR_VERSION >= 3
return PyLong_FromLong( self->dac->getStreamLatency() );
#else
return PyInt_FromLong( self->dac->getStreamLatency() );
#endif
}

static PyObject* RtAudio_getStreamSampleRate(PyRtAudio *self, PyObject *args)
{
if (self == NULL || self->dac == NULL) return NULL;
#if PY_MAJOR_VERSION >= 3
return PyLong_FromLong( self->dac->getStreamSampleRate() );
#else
return PyInt_FromLong( self->dac->getStreamSampleRate() );
#endif
}

static PyObject* RtAudio_showWarnings(PyRtAudio *self, PyObject *args)
@@ -526,10 +603,8 @@ extern "C" {
{NULL}
};


static PyTypeObject RtAudio_type = {
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
PyVarObject_HEAD_INIT(NULL, 0)
"rtaudio.RtAudio", /*tp_name*/
sizeof(RtAudio), /*tp_basicsize*/
0, /*tp_itemsize*/
@@ -578,22 +653,43 @@ extern "C" {
//0, /* Type attribute cache version tag. Added in version 2.6 */
};


#if PY_MAJOR_VERSION >= 3
static PyModuleDef RtAudio_module = {
PyModuleDef_HEAD_INIT,
"RtAudio",
"RtAudio wrapper.",
};
#endif

#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
#define PyMODINIT_FUNC void
#endif
PyMODINIT_FUNC
initrtaudio(void)
#if PY_MAJOR_VERSION >= 3
PyInit_rtaudio(void)
#else
initrtaudio(void)
#endif
{
PyEval_InitThreads();
if (!PyEval_ThreadsInitialized())
PyEval_InitThreads();

if (PyType_Ready(&RtAudio_type) < 0)
#if PY_MAJOR_VERSION >= 3
return NULL;
#else
return;
#endif

#if PY_MAJOR_VERSION >= 3
PyObject* module = PyModule_Create(&RtAudio_module);
if (module == NULL)
return NULL;
#else
PyObject* module = Py_InitModule3("rtaudio", NULL, "RtAudio wrapper.");
if (module == NULL)
return;
#endif

Py_INCREF(&RtAudio_type);
PyModule_AddObject(module, "RtAudio", (PyObject *)&RtAudio_type);
@@ -601,5 +697,10 @@ extern "C" {
RtAudioErrorException = PyErr_NewException("rtaudio.RtError", NULL, NULL);
Py_INCREF(RtAudioErrorException);
PyModule_AddObject(module, "RtError", RtAudioErrorException);
#if PY_MAJOR_VERSION >= 3
return module;
#else
return;
#endif
}
}

+ 0
- 1
contrib/python/pyrtaudio/setup.py View File

@@ -40,7 +40,6 @@ elif OSNAME == 'Windows':
extra_compile_args.append('-EHsc')



audio = Extension('rtaudio',
sources=sources,
libraries=libraries,


Loading…
Cancel
Save