Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* Rhodon Tracker - All-In-One Music studio
- * Copyright (C) 2013 Henrik Andersson <[email protected]>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- #include "instruments/csound_instrument.h"
- #include <csound/csound.h>
- #include <string.h>
- #define RT_CSOUND_INSTRUMENT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), RT_TYPE_CSOUND_INSTRUMENT, RTCsoundInstrumentPrivate))
- typedef struct _controller_def_t
- {
- float default_value;
- float min_value;
- float max_value;
- } _controller_def_t;
- struct _RTCsoundInstrumentPrivate
- {
- CSOUND *csound;
- gboolean loaded;
- MYFLT *aout;
- int aout_channels;
- guint control_cnt;
- gchar **control_names;
- MYFLT *control_ports;
- _controller_def_t *control_def;
- GQueue *midi_events;
- };
- G_DEFINE_TYPE(RTCsoundInstrument, rt_csound_instrument, RT_TYPE_INSTRUMENT)
- static int
- _csound_instrument_midi_device_open_cb(CSOUND *csound, void **userdata, const char *devname)
- {
- g_message("Csound Instrument: Midi device open callback");
- *userdata = csoundGetHostData(csound);
- return 0;
- }
- static int
- _csound_instrument_midi_read_cb(CSOUND *csound, void *userdata, unsigned char *buf, int bytes)
- {
- gint cnt;
- guint32 midi;
- RTCsoundInstrument *self;
- g_assert(userdata != NULL);
- self = RT_CSOUND_INSTRUMENT(userdata);
- cnt = 0;
- while(!g_queue_is_empty(self->priv->midi_events) && cnt <= (bytes-3))
- {
- midi = GPOINTER_TO_UINT(g_queue_peek_head(self->priv->midi_events));
- buf[cnt+0] = (unsigned char) ((midi & 0xff0000) >> 16);
- buf[cnt+1] = (unsigned char) ((midi & 0xff00) >> 8);
- buf[cnt+2] = (unsigned char) (midi & 0xff);
- g_message("Csound Instrument: Midi event %.2x%.2x%.2x",
- buf[cnt], buf[cnt+1], buf[cnt+2]);
- g_queue_pop_head(self->priv->midi_events);
- switch (buf[cnt] & 0xF0) {
- case 0x80: /* note off */
- case 0x90: /* note on */
- case 0xA0: /* polyphonic pressure */
- case 0xB0: /* control change */
- case 0xE0: /* pitch bend */
- cnt += 3;
- break;
- case 0xC0: /* program change */
- case 0xD0: /* channel pressure */
- cnt += 2;
- break;
- case 0xF0:
- switch (buf[cnt]) {
- case 0xF8: /* timing clock */
- case 0xFA: /* start */
- case 0xFB: /* continue */
- case 0xFC: /* stop */
- case 0xFF: /* reset */
- cnt++;
- }
- break; /* ignore any other message */
- }
- }
- return cnt;
- }
- static const gchar *
- _csound_instrument_program_name(RTMachine *machine, guint index)
- {
- return NULL;
- }
- static void
- _csound_instrument_program_set(RTMachine *machine, guint index)
- {
- }
- static void
- _csound_instrument_note_on(RTInstrument *self, guint8 note, guint8 velocity)
- {
- RTCsoundInstrument *synth;
- guint8 channel;
- guint32 midi;
- synth = RT_CSOUND_INSTRUMENT(self);
- channel = 0;
- midi = (0x90 | channel) << 16 | (note) << 8 | velocity;
- g_queue_push_tail(synth->priv->midi_events,
- GUINT_TO_POINTER(midi));
- }
- static void
- _csound_instrument_note_off(RTInstrument *self, guint8 note)
- {
- RTCsoundInstrument *synth;
- guint8 channel;
- guint32 midi;
- synth = RT_CSOUND_INSTRUMENT(self);
- channel = 0;
- midi = (0x80 | channel) << 16 | (note) << 8 | 0;
- g_queue_push_tail(synth->priv->midi_events,
- GUINT_TO_POINTER(midi));
- }
- static const gchar *
- _csound_instrument_controller_name(RTMachine *machine, guint index)
- {
- RTCsoundInstrument *self;
- self = RT_CSOUND_INSTRUMENT(machine);
- if (index >= self->priv->control_cnt)
- return NULL;
- return self->priv->control_names[index];
- }
- static void
- _csound_instrument_controller_get_range(RTMachine *machine, guint index,
- float *min, float *max)
- {
- RTCsoundInstrument *self;
- self = RT_CSOUND_INSTRUMENT(machine);
- if (index >= self->priv->control_cnt)
- return;
- /* sanity checking */
- if (self->priv->control_def[index].min_value >=
- self->priv->control_def[index].max_value)
- return;
- *min = self->priv->control_def[index].min_value;
- *max = self->priv->control_def[index].max_value;
- }
- static float
- _csound_instrument_controller_get_default(RTMachine *machine, guint index)
- {
- RTCsoundInstrument *self;
- self = RT_CSOUND_INSTRUMENT(machine);
- if (index >= self->priv->control_cnt)
- return 1.0;
- return self->priv->control_def[index].default_value;
- }
- static float
- _csound_instrument_controller_get_value(RTMachine *machine, guint index)
- {
- RTCsoundInstrument *self;
- int err;
- self = RT_CSOUND_INSTRUMENT(machine);
- if (index >= self->priv->control_cnt)
- return NAN;
- return csoundGetControlChannel(self->priv->csound,
- self->priv->control_names[index],
- &err);
- }
- static void
- _csound_instrument_controller_set_value(RTMachine *machine, guint index, float value)
- {
- RTCsoundInstrument *self;
- self = RT_CSOUND_INSTRUMENT(machine);
- if (index >= self->priv->control_cnt)
- return;
- csoundSetControlChannel(self->priv->csound,
- self->priv->control_names[index],
- self->priv->control_ports[index]);
- }
- static void
- _csound_instrument_process(RTMachine *self, float *left, float *right, size_t want_frames)
- {
- RTCsoundInstrument *csound;
- static guint iframes = 0;
- guint i, ksmps;
- MYFLT scale;
- csound = RT_CSOUND_INSTRUMENT(self);
- ksmps = csoundGetKsmps(csound->priv->csound);
- scale = csoundGet0dBFS(csound->priv->csound);
- #if 0
- /* update controllers */
- for (i = 0; i < csound->priv->control_cnt; i++)
- csoundSetControlChannel(csound->priv->csound,
- csound->priv->control_names[i],
- csound->priv->control_ports[i]);
- #endif
- /* process samples */
- for (i = 0; i < want_frames; i++, iframes++)
- {
- if (iframes == ksmps)
- {
- csoundPerformKsmps(csound->priv->csound);
- iframes = 0;
- }
- right[i] = left[i] = (csound->priv->aout[iframes] / scale);
- }
- }
- static void
- _csound_dispose(GObject *obj)
- {
- G_OBJECT_CLASS(rt_csound_instrument_parent_class)->dispose(obj);
- }
- static void
- _csound_finalize(GObject *obj)
- {
- RTCsoundInstrument *self;
- self = RT_CSOUND_INSTRUMENT(obj);
- /* destroy csound */
- csoundCleanup(self->priv->csound);
- csoundDestroy(self->priv->csound);
- G_OBJECT_CLASS(rt_csound_instrument_parent_class)->finalize(obj);
- }
- static void
- rt_csound_instrument_class_init(RTCsoundInstrumentClass *klass)
- {
- GObjectClass *class;
- RTInstrumentClass *ic;
- RTMachineClass *mc;
- g_type_class_add_private(klass, sizeof(RTCsoundInstrumentPrivate));
- class = G_OBJECT_CLASS(klass);
- class->dispose = _csound_dispose;
- class->finalize = _csound_finalize;
- /* Instrument virtual funcitons */
- ic = RT_INSTRUMENT_CLASS(klass);
- ic->note_on = _csound_instrument_note_on;
- ic->note_off = _csound_instrument_note_off;
- /* Machine virtual functions */
- mc = RT_MACHINE_CLASS(klass);
- mc->process = _csound_instrument_process;
- mc->controller_name = _csound_instrument_controller_name;
- mc->controller_set_value = _csound_instrument_controller_set_value;
- mc->controller_get_value = _csound_instrument_controller_get_value;
- mc->controller_get_default = _csound_instrument_controller_get_default;
- mc->controller_get_range = _csound_instrument_controller_get_range;
- mc->program_name = _csound_instrument_program_name;
- mc->program_set = _csound_instrument_program_set;
- }
- static void
- rt_csound_instrument_init(RTCsoundInstrument *self)
- {
- self->priv = RT_CSOUND_INSTRUMENT_GET_PRIVATE(self);
- g_object_set(self,
- "name", "Csound",
- NULL);
- self->priv->midi_events = g_queue_new();
- g_queue_clear(self->priv->midi_events);
- self->priv->csound = csoundCreate(self);
- }
- gboolean
- rt_csound_instrument_load(RTCsoundInstrument *self, const gchar *filename)
- {
- volatile guint i;
- gint res;
- gint argc;
- char **argv;
- controlChannelInfo_t *clst;
- controlChannelHints_t hints;
- guint ci = 0;
- /* compile csound instrument */
- argc = 3;
- argv = g_malloc(sizeof(char *) * argc);
- argv[0] = "csound";
- argv[1] = filename;
- argv[2] = "-+rtmidi=null";
- /* setup csound audio output */
- csoundSetOption(self->priv->csound, "--nosound");
- csoundSetOption(self->priv->csound, "--sample-rate=44100");
- csoundSetOption(self->priv->csound, "--control-rate=4410");
- csoundSetOutput(self->priv->csound, "dac", NULL, NULL);
- csoundSetRTAudioModule(self->priv->csound, "null");
- csoundSetHostImplementedAudioIO(self->priv->csound, 1, 0);
- /* setup csound midi input requires rtmidi=null */
- csoundSetExternalMidiInOpenCallback(self->priv->csound,
- _csound_instrument_midi_device_open_cb);
- csoundSetExternalMidiReadCallback(self->priv->csound,
- _csound_instrument_midi_read_cb);
- /* compile program */
- res = csoundCompile(self->priv->csound, argc, argv);
- if (res != CSOUND_SUCCESS)
- {
- g_warning("Csound Instrument: Failed to compile '%s'", filename);
- return FALSE;
- }
- /* turn of score events, only use live performance */
- csoundSetScorePending(self->priv->csound, 1);
- /* get the number of output channels */
- self->priv->aout_channels = csoundGetNchnls(self->priv->csound);
- self->priv->aout = csoundGetSpout(self->priv->csound);
- /* get the channel list */
- res = csoundListChannels(self->priv->csound, &clst);
- if (res == 0)
- {
- g_warning("CSound Instrument: No channels defined.");
- return FALSE;
- }
- if (res == CSOUND_MEMORY)
- {
- g_warning("CSound Instrument: No memory left for channel list.");
- return FALSE;
- }
- /* parse control channels */
- ci = 0;
- self->priv->control_cnt = 0;
- self->priv->control_names = g_malloc(sizeof(gchar *) * res);
- self->priv->control_ports = g_malloc(sizeof(MYFLT) * res);
- self->priv->control_def = g_malloc(sizeof(_controller_def_t) * res);
- memset(self->priv->control_names, 0, sizeof(gchar *) * res);
- memset(self->priv->control_ports, 0, sizeof(MYFLT) * res);
- memset(self->priv->control_def, 0, sizeof(_controller_def_t) * res);
- memset(&hints, 0, sizeof(controlChannelHints_t));
- for (i = 0; i < res; i++)
- {
- if ((clst[i].type & CSOUND_CONTROL_CHANNEL) == CSOUND_CONTROL_CHANNEL)
- {
- self->priv->control_cnt++;
- self->priv->control_names[ci] = g_strdup(clst[i].name);
- if (!(clst[i].hints.behav & CSOUND_CONTROL_CHANNEL_NO_HINTS))
- {
- self->priv->control_def[i].default_value = clst[i].hints.dflt;
- self->priv->control_def[i].min_value = clst[i].hints.min;
- self->priv->control_def[i].max_value = clst[i].hints.max;
- }
- ci++;
- }
- }
- csoundDeleteChannelList(self->priv->csound, clst);
- g_object_set(self, "name", filename, NULL);
- return TRUE;
- }
Advertisement
Add Comment
Please, Sign In to add comment