drvr_src := src/drvr/driver.c
# add libraries
-ifeq (${DUMMY_D}, 1)
-CFLAGS +=-DHAVE_DUMMY
drvr_src +=src/drvr/dummy.c
-endif
-ifeq (${SPA_D}, 1)
-CFLAGS +=-DHAVE_SPA
-drvr_src +=src/drvr/spa.c
-endif
-ifeq (${ALSA_D}, 1)
-LDFLAGS += -lasound
-CFLAGS +=-DHAVE_ALSA
-drvr_src +=src/drvr/alsa.c
-endif
-ifeq (${JACK_D}, 1)
-LDFLAGS += -ljack
-CFLAGS +=-DHAVE_JACK
-drvr_src +=src/drvr/jack.c
-endif
-ifeq (${PORTAUDIO_D}, 1)
-LDFLAGS += -lportaudio
-CFLAGS +=-DHAVE_PORTAUDIO
-drvr_src +=src/drvr/portaudio.c
-endif
-ifeq (${SOUNDIO_D}, 1)
-LDFLAGS += -lsoundio
-CFLAGS +=-DHAVE_SOUNDIO
-drvr_src +=src/drvr/soundio.c
-endif
-ifeq (${PULSE_D}, 1)
-LDFLAGS += -lpulse-simple
-CFLAGS +=-DHAVE_PULSE
-drvr_src +=src/drvr/pulse.c
-endif
-ifeq (${SNDFILE_D}, 1)
-LDFLAGS += -lsndfile
-CFLAGS +=-DHAVE_SNDFILE
-drvr_src +=src/drvr/sndfile.c
-else
-CFLAGS +=-DNO_LIBSNDFILE
-endif
-ifeq (${PLOT_D}, 1)
-CFLAGS +=-DHAVE_PLOT
-drvr_src +=src/drvr/plot.c
-endif
-ifeq (${SLES_D}, 1)
-LDFLAGS += -lOpenSLES
-CFLAGS +=-DHAVE_SLES
-drvr_src +=src/drvr/sles.c
-endif
# add boolean
ifeq (${USE_GWCOV}, 1)
CFLAGS += -DGWCOV
# handle boolean options
USE_DOUBLE = 0
USE_COVERAGE ?= 0
-USE_MEMCHECK ?= 0
-USE_GWREPL ?= 0
-USE_GWUDP ?= 0
USE_OPTIMIZE ?= 0
-USE_OBSTACK ?= 0
-USE_COLOR ?= 0
-USE_JIT ?= 0
-USE_LTO ?= 0
USE_VMBENCH ?= 0
USE_NOMEMOIZE ?= 0
# handle definitions
# base plugin directories
GWPLUG_DIR ?= $(shell echo ~/.gwplug)
-# handle libraries
-DUMMY_D ?= 1
-SILENT_D ?= 0
-SPA_D ?= 0
-SNDFILE_D ?= 0
-ALSA_D ?= 0
-JACK_D ?= 0
-PORTAUDIO_D ?= 0
-SOUNDIO_D ?= 0
-PULSE_D ?= 0
-PLOT_D ?= 0
-SLES_D ?= 0
-
DEBUG_STACK ?= 0
#COLOR ?= 1
#CFLAGS+= -DCOLOR
+++ /dev/null
-#include <alsa/asoundlib.h>
-#include <alsa/mixer.h>
-#include "gwion_util.h"
-#include "gwion_ast.h"
-#include "oo.h"
-#include "vm.h"
-#include "driver.h"
-
-#ifndef SP_ALSA_ACCESS
-#define SP_ALSA_ACCESS SND_PCM_ACCESS_RW_INTERLEAVED
-#endif
-
-#ifdef USE_DOUBLE
-#define ALSA_FORMAT SND_PCM_FORMAT_FLOAT64
-#else
-#define ALSA_FORMAT SND_PCM_FORMAT_FLOAT
-#endif
-/*
-struct AlsaNi {
- void** buf;
- void* bufi;
-};
-*/
-struct AlsaInfo {
- snd_pcm_t* handle;
- snd_pcm_t *pcm_in, *pcm_out;
- SPFLOAT **in_buf, **out_buf;
- void **_in_buf, **_out_buf;
- void *in_bufi, *out_bufi;
-};
-
-static int sp_alsa_init(DriverInfo* di, const char* device,
- int stream, int mode) {
- struct AlsaInfo* info = (struct AlsaInfo*)di->data;
- static snd_pcm_t* handle;
- snd_pcm_hw_params_t* params;
- uint num = (uint)di->bufnum;
- int dir = 0;
-
- if(snd_pcm_open(&handle, device, stream, mode) > 0 || !handle)
- return GW_ERROR;
- snd_pcm_hw_params_alloca(¶ms);
-
- if(snd_pcm_hw_params_any(handle, params) > 0) {
- snd_pcm_close(handle);
- return GW_ERROR;
- }
-
- if(!snd_pcm_hw_params_test_access(handle, params, SP_ALSA_ACCESS))
- snd_pcm_hw_params_set_access(handle, params, SP_ALSA_ACCESS);
-
- if(!snd_pcm_hw_params_test_format(handle, params, ALSA_FORMAT))
- snd_pcm_hw_params_set_format(handle, params, ALSA_FORMAT);
-
- if(!snd_pcm_hw_params_test_rate(handle, params, di->sr, dir))
- snd_pcm_hw_params_set_rate_near(handle, params, &di->sr, &dir);
-
- if(!snd_pcm_hw_params_test_channels(handle, params, (uint)di->chan))
- snd_pcm_hw_params_set_channels(handle, params, (uint)di->chan);
- else return GW_ERROR;
-
- snd_pcm_uframes_t size = di->bufsize;
- if(snd_pcm_hw_params_set_period_size_near(handle, params, &size, &dir))
- return GW_ERROR;
- di->bufsize = size;
- if(snd_pcm_hw_params_set_periods_near(handle, params, &num, &dir))
- return GW_ERROR;
- di->bufnum = num;
- if(snd_pcm_hw_params(handle, params))
- return GW_ERROR;
-
- snd_pcm_hw_params_get_rate_max(params, &di->sr, &dir);
- snd_pcm_hw_params_set_rate_near(handle, params, &di->sr, &dir);
- info->handle = handle;
- return GW_OK;
-}
-
-static void alsa_run_init(VM* vm __attribute__((unused)), DriverInfo* di) {
- struct AlsaInfo* info = (struct AlsaInfo*)di->data;
- snd_pcm_hwsync(info->pcm_out);
- snd_pcm_start(info->pcm_out);
- snd_pcm_hwsync(info->pcm_in);
- snd_pcm_start(info->pcm_in);
-}
-
-static m_bool alsa_ini(VM* vm __attribute__((unused)), DriverInfo* di) {
- struct AlsaInfo* info = (struct AlsaInfo*)xcalloc(1, sizeof(struct AlsaInfo));
- di->data = info;
- if(sp_alsa_init(di, di->card, SND_PCM_STREAM_PLAYBACK, 0) < 0) {
- err_msg(0, "problem with playback");
- return GW_ERROR;
- }
- info->pcm_out = info->handle;
- di->out = di->chan;
- if(sp_alsa_init(di, di->card, SND_PCM_STREAM_CAPTURE, SND_PCM_ASYNC |
- SND_PCM_NONBLOCK) < 0) {
- err_msg(0, "problem with capture");
- return GW_ERROR;
- }
- info->pcm_in = info->handle;
- di->in = di->chan;
- return GW_OK;
-}
-
-static void alsa_run_init_non_interleaved(VM* vm, DriverInfo* di) {
- struct AlsaInfo* info = (struct AlsaInfo*) di->data;
- info->in_buf = (m_float**)xcalloc(vm->bbq->nchan, SZ_FLOAT);
- info->out_buf = (m_float**)xcalloc(vm->bbq->nchan, SZ_FLOAT);
- info->_out_buf = (void**)xcalloc(vm->bbq->nchan, SZ_INT);
- info->_in_buf = (void**)xcalloc(vm->bbq->nchan, SZ_INT);
- for(m_uint i = 0; i < (m_uint)vm->bbq->nchan; i++) {
- info->out_buf[i] = (m_float*)xcalloc(di->bufsize, SZ_FLOAT);
- info->_out_buf[i] = info->out_buf[i];
- info->in_buf[i] = (m_float*)xcalloc(di->bufsize, SZ_FLOAT);
- info->_in_buf[i] = info->in_buf[i];
- }
-}
-
-static void alsa_run_non_interleaved(VM* vm, DriverInfo* di) {
- struct AlsaInfo* info = (struct AlsaInfo*) di->data;
- while(vm->is_running) {
- snd_pcm_readn(info->pcm_in, info->_in_buf, di->bufsize);
- LOOP_OPTIM
- for(m_uint i = 0; i < di->bufsize; i++) {
- for(m_uint chan = 0; chan < (m_uint)vm->bbq->nchan; chan++)
- vm->bbq->in[chan] = ((m_float**)(info->_in_buf))[chan][i];
- di->run(vm);
- LOOP_OPTIM
- for(m_uint chan = 0; chan < (m_uint)vm->bbq->nchan; chan++)
- info->out_buf[chan][i] = vm->bbq->out[chan];
- ++vm->bbq->pos;
- }
- if(snd_pcm_writen(info->pcm_out, info->_out_buf, di->bufsize) < 0)
- snd_pcm_prepare(info->pcm_out);
- }
-}
-
-static void alsa_run_interleaved(VM* vm, DriverInfo* di) {
- struct AlsaInfo* info = (struct AlsaInfo*) di->data;
- while(vm->is_running) {
- m_int j = 0, k = 0;
- snd_pcm_readi(info->pcm_in, info->in_bufi, di->bufsize);
- LOOP_OPTIM
- for(m_uint i = 0; i < di->bufsize; i++) {
- LOOP_OPTIM
- for(m_uint chan = 0; chan < (m_uint)vm->bbq->nchan; chan++)
- vm->bbq->in[chan] = ((m_float*)(info->in_bufi))[j++];
- di->run(vm);
- LOOP_OPTIM
- for(m_uint chan = 0; chan < (m_uint)vm->bbq->nchan; chan++)
- ((m_float*)info->out_bufi)[k++] = vm->bbq->out[chan];
- ++vm->bbq->pos;
- }
- if(snd_pcm_writei(info->pcm_out, info->out_bufi, di->bufsize) < 0)
- snd_pcm_prepare(info->pcm_out);
- }
-}
-
-static void alsa_run(VM* vm, DriverInfo* di) {
- struct AlsaInfo* info = (struct AlsaInfo*) di->data;
- alsa_run_init(vm, di);
- if(SP_ALSA_ACCESS == SND_PCM_ACCESS_RW_NONINTERLEAVED) {
- alsa_run_init_non_interleaved(vm, di);
- alsa_run_non_interleaved(vm, di);
- } else {
- info->in_bufi = (void*)xcalloc(vm->bbq->nchan * di->bufsize, SZ_FLOAT);
- info->out_bufi = (void*)xcalloc(vm->bbq->nchan * di->bufsize, SZ_FLOAT);
- alsa_run_interleaved(vm, di);
- }
-}
-
-static void alsa_del_non_interleaved(VM* vm, struct AlsaInfo* info) {
- if(info->in_buf && info->out_buf) {
- for(m_uint chan = 0; chan < (m_uint)vm->bbq->nchan; chan++) {
- free(info->in_buf[chan]);
- free(info->out_buf[chan]);
- }
- free(info->in_buf);
- free(info->out_buf);
- }
- if(info->_in_buf)
- free(info->_in_buf);
- if(info->_out_buf)
- free(info->_out_buf);
-}
-
-static void alsa_del(VM* vm, DriverInfo* di) {
- struct AlsaInfo* info = (struct AlsaInfo*) di->data;
- if(info->pcm_in)
- snd_pcm_close(info->pcm_in);
- if(info->pcm_out)
- snd_pcm_close(info->pcm_out);
- snd_config_update_free_global();
- if(SP_ALSA_ACCESS == SND_PCM_ACCESS_RW_NONINTERLEAVED)
- alsa_del_non_interleaved(vm, info);
- else {
- if(info->in_bufi)
- free(info->in_bufi);
- if(info->out_bufi)
- free(info->out_bufi);
- }
- free(info);
-}
-
-void alsa_driver(Driver* d) {
- d->ini = alsa_ini;
- d->run = alsa_run;
- d->del = alsa_del;
-}
-
+++ /dev/null
-
-#include <stdlib.h>
-#include <jack/jack.h>
-
-#include <unistd.h> // for sleep
-
-#include "gwion_util.h"
-#include "gwion_ast.h"
-#include "oo.h"
-#include "vm.h"
-#include "driver.h"
-
-struct JackInfo {
- jack_port_t** iport;
- jack_port_t** oport;
- jack_client_t* client;
- VM* vm;
-};
-
-static void gwion_shutdown(void *arg) {
- VM *vm = (VM *)arg;
- vm->is_running = 0;
-}
-
-static void inner_cb(struct JackInfo* info, jack_default_audio_sample_t** in,
- jack_default_audio_sample_t** out, jack_nframes_t nframes) {
- jack_nframes_t frame;
- VM* vm = info->vm;
- m_uint chan;
- for(frame = 0; frame < nframes; frame++) {
- for(chan = 0; chan < vm->bbq->n_in; chan++)
- vm->bbq->in[chan] = in[chan][frame];
- vm_run(vm);
- for(chan = 0; chan < (m_uint)vm->bbq->nchan; chan++)
- out[chan][frame] = vm->bbq->out[chan];
- ++vm->bbq->pos;
- }
-}
-
-static int gwion_cb(jack_nframes_t nframes, void *arg) {
- m_uint chan;
- struct JackInfo* info = (struct JackInfo*)arg;
- VM* vm = info->vm;
- jack_default_audio_sample_t * in[vm->bbq->n_in];
- jack_default_audio_sample_t * out[vm->bbq->nchan];
- for(chan = 0; chan < vm->bbq->n_in; chan++)
- in[chan] = jack_port_get_buffer(info->iport[chan], nframes);
- for(chan = 0; chan < (m_uint)vm->bbq->nchan; chan++)
- out[chan] = jack_port_get_buffer(info->oport[chan], nframes);
- inner_cb(info, in, out, nframes);
- return 0;
-}
-
-static m_bool init_client(VM* vm, struct JackInfo* info) {
- jack_status_t status;
- info->client = jack_client_open("Gwion", JackNullOption, &status, NULL);
- if(!info->client) {
- gw_err("jack_client_open() failed, status = 0x%2.0x\n", status);
- if(status & JackServerFailed)
- gw_err("Unable to connect to JACK server\n");
- return GW_ERROR;
- }
- info->vm = vm;
- jack_set_process_callback(info->client, gwion_cb, info);
- jack_on_shutdown(info->client, gwion_shutdown, vm);
- return GW_OK;
-}
-
-static m_bool set_chan(struct JackInfo* info, m_uint nchan, m_bool input) {
- char chan_name[50];
- m_uint chan;
- jack_port_t** port = input ? info->iport : info->oport;
- for(chan = 0; chan < nchan; chan++) {
- sprintf(chan_name, input ? "input_%ld" : "output_%ld", chan);
- if(!(port[chan] = jack_port_register(info->client, chan_name,
- JACK_DEFAULT_AUDIO_TYPE, input ?
- JackPortIsInput : JackPortIsOutput , chan))) {
- gw_err("no more JACK %s ports available\n", input ?
- "input" : "output");
- return GW_ERROR;
- }
- }
- return GW_OK;
-}
-
-static m_bool jack_ini(VM* vm, DriverInfo* di) {
- struct JackInfo* info = (struct JackInfo*)xmalloc(sizeof(struct JackInfo));
- info->iport = (jack_port_t**)xmalloc(sizeof(jack_port_t *) * di->in);
- info->oport = (jack_port_t**)xmalloc(sizeof(jack_port_t *) * di->out);
- CHECK_BB(init_client(vm, info))
- CHECK_BB(set_chan(info, di->out, 0))
- CHECK_BB(set_chan(info, di->in, 1))
- di->sr = jack_get_sample_rate(info->client);
- di->data = info;
- return GW_OK;
-}
-
-static m_bool connect_ports(struct JackInfo* info, const char** ports,
- m_uint nchan, m_bool input) {
- m_uint chan;
- jack_port_t** jport = input ? info->iport : info->oport;
- for(chan = 0; chan < nchan; chan++) {
- const char* l = input ? ports[chan] : jack_port_name(jport[chan]);
- const char* r = input ? jack_port_name(jport[chan]) : ports[chan];
- if(jack_connect(info->client, l, r)) {
- gw_err("cannot connect %s ports\n", input ? "input" : "output");
- return GW_ERROR;
- }
- }
- return GW_OK;
-}
-
-static m_bool init_ports(struct JackInfo* info, m_uint nchan, m_bool input) {
- m_bool ret;
- const char** ports = jack_get_ports(info->client, NULL, NULL,
- JackPortIsPhysical | (input ? JackPortIsOutput : JackPortIsInput));
- if(!ports)
- return GW_ERROR;
- ret = connect_ports(info, ports, nchan, input);
- free(ports);
- return ret;
-}
-
-static void jack_run(VM* vm, DriverInfo* di) {
- struct JackInfo* info = (struct JackInfo*)di->data;
- if(jack_activate(info->client)) {
- gw_err("cannot activate client\n");
- return;
- }
- if(init_ports(info, di->out, 0) < 0 || init_ports(info, di->in, 1) < 0)
- return;
- while(vm->is_running)
- usleep(10);
-}
-
-static void jack_del(VM* vm __attribute__((unused)), DriverInfo* di) {
- struct JackInfo* info = (struct JackInfo*)di->data;
- jack_deactivate(info->client);
- jack_client_close(info->client);
- free(info->iport);
- free(info->oport);
-}
-
-void jack_driver(Driver* d) {
- d->ini = jack_ini;
- d->run = jack_run;
- d->del = jack_del;
-}
+++ /dev/null
-#include <stdlib.h>
-#include "gwion_util.h"
-#include "gwion_ast.h"
-#include "oo.h"
-#include "vm.h"
-#include "driver.h"
-
-static m_bool plot_ini(VM* vm __attribute__((unused)), DriverInfo* di) {
- FILE** sf = (FILE**)xcalloc(di->chan, sizeof(void*));
- char tmp[140];
- if(di->chan == 1) {
- sprintf(tmp, "%s.wav", di->card);
- sf[0] = fopen(tmp, "w");
- } else LOOP_OPTIM for(m_uint chan = 0; chan < di->chan; chan++) {
- sprintf(tmp, "%s_%02" UINT_F ".plot", di->card, chan);
- sf[chan] = fopen(tmp, "w");
- }
- di->data = sf;
- return GW_OK;
-}
-
-static void plot_run(VM* vm __attribute__((unused)), DriverInfo* di) {
- m_uint i, chan;
- FILE** sf = (FILE**)di->data;
- while(vm->is_running) {
- for(i = 0; i < di->bufsize; i++) {
- di->run(vm);
- LOOP_OPTIM
- for(chan = 0; chan < di->chan; chan++)
- fprintf(sf[chan], "%"UINT_F" %g\n", vm->bbq->pos, (const m_float)vm->bbq->out[chan]);
- ++vm->bbq->pos;
- }
- }
-}
-
-static void plot_del(VM* vm __attribute__((unused)), DriverInfo* di) {
- FILE** sf = (FILE**)di->data;
- LOOP_OPTIM
- for(m_uint i = 0; i < di->chan; i++)
- fclose(sf[i]);
- free(sf);
-}
-
-void plot_driver(Driver* d) {
- d->ini = plot_ini;
- d->run = plot_run;
- d->del = plot_del;
-}
-
+++ /dev/null
-#include <portaudio.h>
-#include "gwion_util.h"
-#include "gwion_ast.h"
-#include "oo.h"
-#include "vm.h"
-#include "type.h"
-#include "object.h"
-#include "ugen.h"
-#include "driver.h"
-
-#define SAMPLE_RATE (48000)
-#define FRAMES_PER_BUFFER (64)
-
-struct PaInfo {
- PaStream *stream;
- PaStreamParameters outputParameters;
- PaStreamParameters inputParameters;
-};
-
-static int callback(const void *inputBuffer, void *outputBuffer,
- unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo* timeInfo __attribute__((unused)),
- PaStreamCallbackFlags statusFlags __attribute__((unused)), void *userData) {
- VM* vm = (VM*)userData;
- float *in = (float*)inputBuffer;
- float *out = (float*)outputBuffer;
- m_uint i, j;
- for(i = 0; i < framesPerBuffer; i++) {
- for(j = 0; j < vm->bbq->n_in; j++)
- vm->bbq->in[j] = *in++;
-// di->run(vm);
- vm_run(vm);
- for(j = 0; j < (m_uint)vm->bbq->nchan; j++)
- *out++ = vm->bbq->out[j];
- ++vm->bbq->pos;
- }
- return paContinue;
-}
-
-static m_bool ini(VM* vm, DriverInfo* di) {
- struct PaInfo* info = (struct PaInfo*)xmalloc(sizeof(struct PaInfo*));
- di->data = info;
- if(Pa_Initialize() != paNoError)
- return GW_ERROR;
- info->outputParameters.device = Pa_GetDefaultOutputDevice();
- if(info->outputParameters.device == paNoDevice) {
- gw_err("Error: No default output device.\n");
- goto error;
- }
- info->outputParameters.channelCount = 2;
- info->outputParameters.sampleFormat = di->format;
- info->outputParameters.suggestedLatency = Pa_GetDeviceInfo(info->outputParameters.device)->defaultLowOutputLatency;
- info->outputParameters.hostApiSpecificStreamInfo = NULL;
-
- info->inputParameters.device = Pa_GetDefaultInputDevice(); /* default output device */
- if(info->inputParameters.device == paNoDevice) {
- gw_err("Error: No default input device.\n");
- goto error;
- }
- info->inputParameters.channelCount = 2;
- info->inputParameters.sampleFormat = paFloat32;
- info->inputParameters.suggestedLatency = Pa_GetDeviceInfo(info->inputParameters.device)->defaultLowOutputLatency;
- info->inputParameters.hostApiSpecificStreamInfo = NULL;
-
- if(Pa_OpenStream(
- &info->stream,
- &info->inputParameters,
- &info->outputParameters,
- di->sr,
- di->bufsize,
- paClipOff,
- callback,
- vm) != paNoError)
- goto error;
- return GW_OK;
-error:
- Pa_Terminate();
- return GW_ERROR;
-}
-
-static void del(VM* vm __attribute__((unused)), DriverInfo* di) {
- struct PaInfo* info = (struct PaInfo*)di->data;
- Pa_StopStream(info->stream);
- Pa_Terminate();
-}
-
-static void run(VM* vm, DriverInfo* di) {
- struct PaInfo* info = (struct PaInfo*)di->data;
- Pa_StartStream(info->stream);
- while(vm->is_running)
- Pa_Sleep(1);
-}
-
-void pa_driver(Driver* d) {
- d->ini = ini;
- d->run = run;
- d->del = del;
-}
+++ /dev/null
-#include <pulse/simple.h>
-#include "gwion_util.h"
-#include "gwion_ast.h"
-#include "oo.h"
-#include "vm.h"
-#include "driver.h"
-
-#define BUFSIZE 1024
-
-//static pa_simple* in;
-//static pa_simple* out;
-
-//static const pa_sample_spec ss = { PA_SAMPLE_FLOAT32NE, 48000, 2};
-
-struct PaInfo {
- pa_simple* in;
- pa_simple* out;
-};
-
-static pa_simple* pulse_open(m_uint direction, pa_sample_spec* ss) {
- return pa_simple_new(NULL, "Gwion", direction,
- NULL, "Gwion", ss, NULL, NULL, NULL);
-}
-
-static m_bool pulse_ini(VM* vm __attribute__((unused)), DriverInfo* di) {
- struct PaInfo* info = (struct PaInfo*)xmalloc(sizeof(struct PaInfo));
- pa_sample_spec ss = { PA_SAMPLE_FLOAT32NE, 48000, 2};
- CHECK_OB((info->out = pulse_open(PA_STREAM_PLAYBACK, &ss)))
- CHECK_OB((info->in = pulse_open(PA_STREAM_RECORD, &ss)))
- di->data = info;
- return GW_OK;
-}
-
-static void pulse_run(VM* vm, DriverInfo* di) {
- int error;
- struct PaInfo* info = (struct PaInfo*)di->data;
- while(vm->is_running) {
- m_uint frame, chan;
- float in_data[BUFSIZE * vm->bbq->nchan];
- float out_data[BUFSIZE * vm->bbq->nchan];
- if(pa_simple_read(info->in, in_data, sizeof(in_data), &error) < 0)
- return;
- for(frame = 0; frame < BUFSIZE; frame++) {
- for(chan = 0; chan < (m_uint)vm->bbq->nchan; chan++)
- vm->bbq->in[chan] = in_data[frame * vm->bbq->nchan + chan];
- di->run(vm);
- for(chan = 0; chan < (m_uint)vm->bbq->nchan; chan++)
- out_data[frame * vm->bbq->nchan + chan] = (float)vm->bbq->out[chan];
- ++vm->bbq->pos;
- }
- if(pa_simple_write(info->out, out_data, sizeof(out_data), &error) < 0)
- return;
- }
- if(pa_simple_drain(info->out, &error) < 0)
- return;
-}
-
-static void pulse_del(VM* vm __attribute__((unused)), DriverInfo* di) {
- struct PaInfo* info = (struct PaInfo*)di->data;
- if(info->in)
- pa_simple_free(info->in);
- if(info->out)
- pa_simple_free(info->out);
- free(info);
-}
-
-void pulse_driver(Driver* d) {
- d->ini = pulse_ini;
- d->run = pulse_run;
- d->del = pulse_del;
-}
+++ /dev/null
-#include <stdio.h>
-#include <string.h>
-#include <SLES/OpenSLES.h>
-#include <SLES/OpenSLES_Android.h>
-#include "vm.h"
-#include "driver.h"
-
-#define BUFSIZE 1024
-#define CHECK_SL(a) if((a) != SL_RESULT_SUCCESS) return GW_ERROR;
-
-typedef struct {
- long l, r;
-} frame_t;
-
-static frame_t out_buf[BUFSIZE];
-static SLObjectItf object;
-static SLEngineItf engine;
-static SLObjectItf player;
-
-static m_bool sles_ini(VM* vm, DriverInfo* di) {
- // create engine
-
- CHECK_SL(slCreateEngine(&object, 0, NULL, 0, NULL, NULL))
- CHECK_SL((*object)->Realize(object, SL_BOOLEAN_FALSE))
-
- CHECK_SL((*object)->GetInterface(object, SL_IID_ENGINE, &engine))
-
- // create output mix
- SLObjectItf outputmixObject;
- CHECK_SL((*engine)->CreateOutputMix(engine, &outputmixObject, 0, NULL, NULL))
- CHECK_SL((*outputmixObject)->Realize(outputmixObject, SL_BOOLEAN_FALSE))
-
- // create audio player
- SLDataSource audiosrc;
- SLDataSink audiosnk;
- SLDataFormat_PCM pcm;
- SLDataLocator_OutputMix locator_outputmix;
- SLDataLocator_BufferQueue locator_bufferqueue;
- locator_bufferqueue.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
- locator_bufferqueue.numBuffers = BUFSIZE;
- locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
- locator_outputmix.outputMix = outputmixObject;
- pcm.formatType = SL_DATAFORMAT_PCM;
- pcm.numChannels = 2;
- pcm.samplesPerSec = SL_SAMPLINGRATE_48;
- pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_32;
- pcm.containerSize = 32;
- pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
- pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
- audiosrc.pLocator = &locator_bufferqueue;
- audiosrc.pFormat = &pcm;
- audiosnk.pLocator = &locator_outputmix;
- audiosnk.pFormat = NULL;
- SLObjectItf playerObject;
- SLInterfaceID ids[1] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE};
- SLboolean flags[1] = {SL_BOOLEAN_TRUE};
- CHECK_SL((*engine)->CreateAudioPlayer(engine, &playerObject,
- &audiosrc, &audiosnk, 1, ids, flags))
- CHECK_SL((*playerObject)->Realize(playerObject, SL_BOOLEAN_FALSE))
- SLPlayItf playerPlay;
- CHECK_SL((*playerObject)->GetInterface(playerObject, SL_IID_PLAY, &playerPlay))
- SLAndroidSimpleBufferQueueItf playerBufferqueue;
- CHECK_SL((*playerObject)->GetInterface(playerObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &playerBufferqueue))
- CHECK_SL((*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING))
- return GW_OK;
-}
-
-static void sles_run(VM* vm, DriverInfo* di) {
- while(vm->is_running) {
- for(m_uint i = 0; i < BUFSIZE; i++) {
- di->run(vm);
- out_buf[i].l = vm->bbq->out[0];
- out_buf[i].r = vm->bbq->out[1];
- }
- }
-}
-
-static void sles_del() {
- if(player)
- (*player)->Destroy(player);
-// if(engine)
-// (*engine)->Destroy(engine);
- if(object)
- (*object)->Destroy(object);
-}
-
-void sles_driver(Driver* d) {
- d->ini = sles_ini;
- d->run = sles_run;
- d->del = sles_del;
-}
-
+++ /dev/null
-#ifdef USE_DOUBLE
-#define sf_write sf_write_double
-#else
-#define sf_write sf_write_float
-#endif
-#include <stdlib.h>
-#include <sndfile.h>
-#include "gwion_util.h"
-#include "gwion_ast.h"
-#include "oo.h"
-#include "vm.h"
-#include "driver.h"
-
-static m_bool sndfile_ini(VM* vm __attribute__((unused)), DriverInfo* di) {
- SNDFILE** sf = (SNDFILE**)xcalloc(di->chan, sizeof(void*));
- char tmp[140];
- SF_INFO info;
- info.samplerate = di->sr;
- info.channels = 1;
- info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_24;
- m_uint chan;
- if(di->chan == 1) {
- sprintf(tmp, "%s.wav", di->card);
- sf[0] = sf_open(tmp, SFM_WRITE, &info);
- } else for(chan = 0; chan < di->chan; chan++) {
- sprintf(tmp, "%s_%02" UINT_F ".wav", di->card, chan);
- sf[chan] = sf_open(tmp, SFM_WRITE, &info);
- }
- di->data = sf;
- return GW_OK;
-}
-
-static void sndfile_run(VM* vm, DriverInfo* di) {
- m_uint i, chan;
- SNDFILE** sf = (SNDFILE**)di->data;
- m_float buf[di->chan][di->bufsize];
- while(vm->is_running) {
- for(i = 0; i < di->bufsize; i++) {
- di->run(vm);
- for(chan = 0; chan < di->chan; chan++)
- buf[chan][i] = vm->bbq->out[chan];
- ++vm->bbq->pos;
- }
- for(chan = 0; chan < di->chan; chan++)
- sf_write(sf[chan], (const m_float*)buf[chan], di->bufsize);
- }
-}
-
-static void sndfile_del(VM* vm __attribute__((unused)), DriverInfo* di) {
- SNDFILE** sf = (SNDFILE**)di->data;
- for(m_uint i = 0; i < di->chan; i++)
- sf_close(sf[i]);
- free(sf);
-}
-
-void sndfile_driver(Driver* d) {
- d->ini = sndfile_ini;
- d->run = sndfile_run;
- d->del = sndfile_del;
-}
-
+++ /dev/null
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-#include <soundio/soundio.h>
-#include "gwion_util.h"
-#include "gwion_ast.h"
-#include "oo.h"
-#include "vm.h"
-#include "driver.h"
-
-typedef struct SoundIoChannelArea* Areas;
-typedef struct SoundIoOutStream * Out;
-typedef struct SoundIoInStream * In;
-
-struct SioInfo {
- VM* vm;
- DriverInfo* di;
- struct SoundIo *soundio;
- struct SoundIoOutStream *outstream;
- struct SoundIoInStream *instream;
- struct SoundIoDevice *out_device;
- struct SoundIoDevice *in_device;
- enum SoundIoBackend backend;// = SoundIoBackendNone;
- m_str device_id;
- m_bool raw;
- void (*write_sample)(char *ptr, m_float sample);
- void (*read_sample)(char *ptr, m_float *sample);
-
-};
-
-static void write_sample_s16ne(char *ptr, m_float sample) {
- int16_t *buf = (int16_t *)ptr;
- m_float range = (m_float)INT16_MAX - (m_float)INT16_MIN;
- m_float val = sample * range / 2.0;
- *buf = val;
-}
-
-static void write_sample_s32ne(char *ptr, m_float sample) {
- int32_t *buf = (int32_t *)ptr;
- m_float range = (m_float)INT32_MAX - (m_float)INT32_MIN;
- m_float val = sample * range / 2.0;
- *buf = val;
-}
-
-static void write_sample_float32ne(char *ptr, m_float sample) {
- float *buf = (float*)ptr;
- *buf = sample;
-}
-
-static void write_sample_float64ne(char *ptr, m_float sample) {
- m_float *buf = (m_float *)ptr;
- *buf = sample;
-}
-
-static void read_sample_s16ne(char *ptr, m_float *sample) {
- int16_t *buf = (int16_t *)ptr;
- m_float range = (m_float)INT16_MAX - (m_float)INT16_MIN;
- m_float val = *buf * range / 2.0;
- *sample = val;
-}
-
-static void read_sample_s32ne(char *ptr, m_float *sample) {
- int32_t *buf = (int32_t *)ptr;
- m_float range = (m_float)INT32_MAX - (m_float)INT32_MIN;
- m_float val = *buf * range / 2.0;
- *sample = val;
-}
-
-static void read_sample_float32ne(char *ptr, m_float *sample) {
- *sample = *(float *)ptr;
-}
-
-static void read_sample_float64ne(char *ptr, m_float *sample) {
- *sample = *(m_float *)ptr;
-}
-
-static void underflow_callback(Out outstream __attribute__((unused))) {
- static int count = 0;
- gw_err("underflow %d\n", count++);
-}
-
-static void overflow_callback(In stream __attribute__((unused))) {
- static int count = 0;
- gw_err("overflow %d\n", count++);
-}
-
-static m_bool check_cb_error1(VM* vm, void* data, Areas* areas, int* count, m_bool in) {
- int err = in ?
- soundio_instream_begin_read((In)data, areas, count) :
- soundio_outstream_begin_write((Out)data, areas, count);
- if(err) {
- gw_err("unrecoverable stream error: %s\n", soundio_strerror(err));
- vm->is_running = 0;
- return GW_ERROR;
- }
- return GW_OK;
-}
-
-static m_bool check_cb_error2(VM* vm, void* data, int (*f)(void*)) {
- int err = f(data);
- if(err) {
- gw_err("%s\n", soundio_strerror(err));
- vm->is_running = 0;
- return GW_ERROR;
- }
- return GW_OK;
-}
-
-static void write_callback(Out stream, int min __attribute__((unused)), int left) {
- Areas areas;
- struct SioInfo* info = (struct SioInfo*)stream->userdata;
- VM* vm = info->vm;
- DriverInfo* di = info->di;
- while(left > 0) {
- int count = left;
- if(check_cb_error1(vm, stream, &areas, &count, 0) < 0)
- return;
- if(!count)
- break;
- if(!areas)
- gw_err("Dropped %d frames due to internal underflow\n", count);
- else for(int frame = 0; frame < count; frame++) {
- di->run(vm);
- for(int channel = 0; channel < stream->layout.channel_count; channel++) {
- info->write_sample(areas[channel].ptr, vm->bbq->out[channel]);
- areas[channel].ptr += areas[channel].step;
- }
- ++vm->bbq->pos;
- }
- check_cb_error2(info->vm, stream, (int (*)(void*))soundio_outstream_end_write);
- left -= count;
- }
- soundio_outstream_pause(stream, 0);
-}
-
-static void read_callback(In stream, int min __attribute__((unused)), int left) {
- Areas areas;
- struct SioInfo* info = (struct SioInfo*)stream->userdata;
- VM* vm = info->vm;
- while(left > 0) {
- int count = left;
- if(check_cb_error1(vm, stream, &areas, &count, 1) < 0)
- return;
- if(!count)
- break;
- if(!areas)
- gw_err("Dropped %d frames due to internal overflow\n", count);
- else for(int frame = 0; frame < count; frame += 1) {
- for(int ch = 0; ch < stream->layout.channel_count; ch += 1) {
- info->read_sample(areas[ch].ptr, &vm->bbq->in[ch]);
- areas[ch].ptr += areas[ch].step;
- }
- }
- check_cb_error2(vm, stream, (int(*)(void*))soundio_instream_end_read);
- left -= count;
- }
-}
-
-static m_bool init_soundio(struct SioInfo* info) {
- int err;
- if(!(info->soundio = soundio_create())) {
- gw_err("out of memory\n");
- return GW_ERROR;
- }
- err = (info->backend == SoundIoBackendNone) ?
- soundio_connect(info->soundio) : soundio_connect_backend(info->soundio, info->backend);
- if(err) {
- gw_err("Unable to connect to backend: %s\n", soundio_strerror(err));
- return GW_ERROR;
- }
- soundio_flush_events(info->soundio);
- return GW_OK;
-}
-
-static int get_index(struct SioInfo* info) {
- int selected_device_index = -1;
- if(info->device_id) {
- int device_count = soundio_output_device_count(info->soundio);
- for(int i = 0; i < device_count; i += 1) {
- struct SoundIoDevice *device = soundio_get_output_device(info->soundio, i);
- bool select_this_one = strcmp(device->id, info->device_id) == 0 && device->is_raw == info->raw;
- soundio_device_unref(device);
- if(select_this_one) {
- selected_device_index = i;
- break;
- }
- }
- } else
- selected_device_index = soundio_default_output_device_index(info->soundio);
- if(selected_device_index < 0) {
- gw_err("Output device not found\n");
- return GW_ERROR;
- }
- return selected_device_index;
-}
-
-static m_bool get_device(struct SioInfo* info, int selected_device_index) {
- info->out_device = soundio_get_output_device(info->soundio, selected_device_index);
- if(!info->out_device) {
- gw_err("out of memory\n");
- return GW_ERROR;
- }
- info->in_device = soundio_get_input_device(info->soundio, selected_device_index);
- if(!info->in_device) {
- gw_err("out of memory\n");
- return GW_ERROR;
- }
- return GW_OK;
-}
-
-static m_bool probe(struct SioInfo* info) {
- if(info->out_device->probe_error) {
- gw_err("Cannot probe device: %s\n", soundio_strerror(info->out_device->probe_error));
- return GW_ERROR;
- }
- if(info->in_device->probe_error) {
- gw_err("Cannot probe device: %s\n", soundio_strerror(info->in_device->probe_error));
- return GW_ERROR;
- }
- return GW_OK;
-}
-
-static m_bool out_create(DriverInfo* di) {
- struct SioInfo* info = (struct SioInfo*)di->data;
- info->outstream = soundio_outstream_create(info->out_device);
- if(!info->outstream) {
- gw_err("out of memory\n");
- return GW_ERROR;
- }
- info->outstream->write_callback = write_callback;
- info->outstream->underflow_callback = underflow_callback;
- info->outstream->name = "Gwion output";
- info->outstream->software_latency = 0;
- info->outstream->sample_rate = di->sr;
- info->outstream->userdata = info;
- return GW_OK;
-}
-
-static m_bool in_create(DriverInfo* di) {
- struct SioInfo* info = (struct SioInfo*)di->data;
- info->instream = soundio_instream_create(info->in_device);
- if(!info->instream) {
- gw_err("out of memory\n");
- return GW_ERROR;
- }
- info->instream->read_callback = read_callback;
- info->instream->overflow_callback = overflow_callback;
- info->instream->name = "Gwion input";
- info->instream->software_latency = 0;
- info->instream->sample_rate = di->sr;
- info->instream->userdata = info;
- return GW_OK;
-}
-
-static m_bool out_format(struct SioInfo* info) {
- if(soundio_device_supports_format(info->out_device, SoundIoFormatFloat64NE)) {
- info->outstream->format = SoundIoFormatFloat64NE;
- info->write_sample = write_sample_float64ne;
- } else if(soundio_device_supports_format(info->out_device, SoundIoFormatFloat32NE)) {
- info->outstream->format = SoundIoFormatFloat32NE;
- info->write_sample = write_sample_float32ne;
- } else if(soundio_device_supports_format(info->out_device, SoundIoFormatS32NE)) {
- info->outstream->format = SoundIoFormatS32NE;
- info->write_sample = write_sample_s32ne;
- } else if(soundio_device_supports_format(info->out_device, SoundIoFormatS16NE)) {
- info->outstream->format = SoundIoFormatS16NE;
- info->write_sample = write_sample_s16ne;
- } else {
- gw_err("No suitable device format available.\n");
- return GW_ERROR;
- }
- return GW_OK;
-}
-
-static m_bool in_format(struct SioInfo* info) {
- if(soundio_device_supports_format(info->in_device, SoundIoFormatFloat64NE)) {
- info->instream->format = SoundIoFormatFloat64NE;
- info->read_sample = read_sample_float64ne;
- } else if(soundio_device_supports_format(info->in_device, SoundIoFormatFloat32NE)) {
- info->instream->format = SoundIoFormatFloat32NE;
- info->read_sample = read_sample_float32ne;
- } else if(soundio_device_supports_format(info->in_device, SoundIoFormatS32NE)) {
- info->instream->format = SoundIoFormatS32NE;
- info->read_sample = read_sample_s32ne;
- } else if(soundio_device_supports_format(info->in_device, SoundIoFormatS16NE)) {
- info->instream->format = SoundIoFormatS16NE;
- info->read_sample = read_sample_s16ne;
- } else {
- gw_err("No suitable device format available.\n");
- return GW_ERROR;
- }
- return GW_OK;
-}
-
-static m_bool open_stream(struct SioInfo* info) {
- int err;
- if((err = soundio_outstream_open(info->outstream))) {
- gw_err("unable to open output device: %s", soundio_strerror(err));
- return GW_ERROR;
- }
- if((err = soundio_instream_open(info->instream))) {
- gw_err("unable to open input device: %s", soundio_strerror(err));
- return GW_ERROR;
- }
- return GW_OK;
-}
-
-static m_bool check_layout(struct SioInfo* info) {
- if(info->outstream->layout_error) {
- gw_err("unable to set output channel layout: %s\n",
- soundio_strerror(info->outstream->layout_error));
- return GW_ERROR;
- }
- if(info->instream->layout_error) {
- gw_err("unable to set input channel layout: %s\n",
- soundio_strerror(info->instream->layout_error));
- return GW_ERROR;
- }
- return GW_OK;
-}
-
-static m_bool sio_ini(VM* vm, DriverInfo* di) {
- struct SioInfo* info = (struct SioInfo*)xcalloc(1, sizeof(struct SioInfo));
- info->vm = vm;
- info->di = di;
- info->device_id = di->card;
- info->backend = SoundIoBackendNone;
- di->data = info;
- CHECK_BB(init_soundio(info))
- int selected_device_index = get_index(info);
- CHECK_BB(selected_device_index)
- CHECK_BB(get_device(info, selected_device_index))
- CHECK_BB(probe(info))
- CHECK_BB(out_create(di))
- CHECK_BB(in_create(di))
- CHECK_BB(out_format(info))
- CHECK_BB(in_format(info))
- CHECK_BB(open_stream(info))
- CHECK_BB(check_layout(info))
- return GW_OK;
-}
-
-static void sio_run(VM* vm, DriverInfo* di) {
- struct SioInfo* info = (struct SioInfo*)di->data;
- int err;
- if((err = soundio_instream_start(info->instream))) {
- gw_err("unable to start input device: %s\n", soundio_strerror(err));
- return;
- }
- if((err = soundio_outstream_start(info->outstream))) {
- gw_err("unable to start ouput device: %s\n", soundio_strerror(err));
- return;
- }
- while(vm->is_running)
- soundio_flush_events(info->soundio);
-}
-
-static void sio_del(VM* vm __attribute__((unused)), DriverInfo* di) {
- struct SioInfo* info = (struct SioInfo*)di->data;
- soundio_outstream_destroy(info->outstream);
- soundio_instream_destroy(info->instream);
- soundio_device_unref(info->in_device);
- soundio_device_unref(info->out_device);
- soundio_destroy(info->soundio);
- free(info);
-}
-
-void sio_driver(Driver* d) {
- d->ini = sio_ini;
- d->run = sio_run;
- d->del = sio_del;
-}
+++ /dev/null
-#include <stdlib.h>
-#include <string.h>
-#include <soundpipe.h>
-#include "gwion_util.h"
-#include "gwion_ast.h"
-#include "oo.h"
-#include "vm.h"
-#include "driver.h"
-
-static m_bool spa_ini(VM* vm __attribute__((unused)), DriverInfo* di) {
- di->data = (sp_audio*)xmalloc(sizeof(sp_audio));
- return GW_OK;
-}
-
-static void spa_run(VM* vm, DriverInfo* di) {
- char tmp[strlen(di->card) + 5];
- sp_audio* spa = di->data;
- sprintf(tmp, "%s.spa", di->card);
- if(spa_open(vm->sp, spa, tmp, SPA_WRITE) == SP_NOT_OK) {
- gw_err("Error: could not open file %s.\n", di->card);
- return;
- }
- while(vm->is_running) {
- di->run(vm);
- spa_write_buf(vm->sp, spa, sp->out, sp->nchan);
- ++sp->pos;
- }
-}
-
-static void spa_del(VM* vm __attribute__((unused)), DriverInfo* di) {
- sp_audio* spa = (sp_audio*)di->data;
- spa_close(spa);
- free(spa);
-}
-
-void spa_driver(Driver* d) {
- d->ini = spa_ini;
- d->run = spa_run;
- d->del = spa_del;
-}
}
ANN m_bool gwion_audio(const Gwion gwion, DriverInfo* di) {
+ di->func = dummy_driver;
// get driver from string.
if(di->arg) {
for(m_uint i = 0; i < map_size(&gwion->plug->drv); ++i) {