From: Paul Brossier Date: Mon, 6 Dec 2004 18:51:31 +0000 (+0000) Subject: moved midi functions to ext/ X-Git-Tag: 0.4.0-beta1~1469 X-Git-Url: https://git.aubio.org/?a=commitdiff_plain;h=b60dd4ae028d987b1e9bdbd6b71e62f529465109;p=aubio.git moved midi functions to ext/ --- diff --git a/Makefile.am b/Makefile.am index fc8781c6..76ae2e62 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = src examples doc sounds swig python plugins +SUBDIRS = src ext examples doc sounds swig python plugins EXTRA_DIST = bootstrap VERSION DISTCLEANFILES = autom4te.cache diff --git a/Makefile.in b/Makefile.in index 1b08cb69..0f400b84 100644 --- a/Makefile.in +++ b/Makefile.in @@ -151,7 +151,7 @@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ -SUBDIRS = src examples doc sounds swig python plugins +SUBDIRS = src ext examples doc sounds swig python plugins EXTRA_DIST = bootstrap VERSION DISTCLEANFILES = autom4te.cache subdir = . diff --git a/configure b/configure index 1a9dc0e5..a7d8d55c 100755 --- a/configure +++ b/configure @@ -21053,7 +21053,7 @@ echo "${ECHO_T}$am_cv_python_pyexecdir" >&6 - ac_config_files="$ac_config_files Makefile src/Makefile examples/Makefile sounds/Makefile doc/Makefile python/Makefile python/aubio/Makefile plugins/Makefile plugins/audacity/Makefile plugins/audacity/plug-ins/Makefile plugins/wavesurfer/Makefile plugins/puredata/Makefile swig/Makefile" + ac_config_files="$ac_config_files Makefile src/Makefile ext/Makefile examples/Makefile sounds/Makefile doc/Makefile python/Makefile python/aubio/Makefile plugins/Makefile plugins/audacity/Makefile plugins/audacity/plug-ins/Makefile plugins/wavesurfer/Makefile plugins/puredata/Makefile swig/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure @@ -21613,6 +21613,7 @@ do "aubio.pc" ) CONFIG_FILES="$CONFIG_FILES aubio.pc" ;; "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; "src/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; + "ext/Makefile" ) CONFIG_FILES="$CONFIG_FILES ext/Makefile" ;; "examples/Makefile" ) CONFIG_FILES="$CONFIG_FILES examples/Makefile" ;; "sounds/Makefile" ) CONFIG_FILES="$CONFIG_FILES sounds/Makefile" ;; "doc/Makefile" ) CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; diff --git a/configure.ac b/configure.ac index 17320be7..d6e13495 100644 --- a/configure.ac +++ b/configure.ac @@ -150,6 +150,7 @@ AM_PATH_PYTHON(,,) AC_OUTPUT([ Makefile src/Makefile + ext/Makefile examples/Makefile sounds/Makefile doc/Makefile diff --git a/examples/Makefile.am b/examples/Makefile.am index 1c32606d..eb03387a 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -1,9 +1,8 @@ - #SUBDIRS=onsets # global flags -AM_CFLAGS = -I../src @LADCCA_CFLAGS@ -AM_LDFLAGS = -L../src @LADCCA_LIBS@ -laubio +AM_CFLAGS = -I../src -I../ext @LADCCA_CFLAGS@ +AM_LDFLAGS = -L../src -L../ext @LADCCA_LIBS@ -laubioext -laubio #AM_SOURCES = utils.c # add your programs to this list diff --git a/examples/Makefile.in b/examples/Makefile.in index 06f720d7..d2b6c4a0 100644 --- a/examples/Makefile.in +++ b/examples/Makefile.in @@ -155,8 +155,8 @@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ # global flags -AM_CFLAGS = -I../src @LADCCA_CFLAGS@ -AM_LDFLAGS = -L../src @LADCCA_LIBS@ -laubio +AM_CFLAGS = -I../src -I../ext @LADCCA_CFLAGS@ +AM_LDFLAGS = -L../src -L../ext @LADCCA_LIBS@ -laubioext -laubio #AM_SOURCES = utils.c # add your programs to this list diff --git a/examples/aubionotes.c b/examples/aubionotes.c index 36840d3a..aad56a15 100644 --- a/examples/aubionotes.c +++ b/examples/aubionotes.c @@ -23,6 +23,7 @@ #include #include // how do i do a floorf with a mask again ? #include "aubio.h" +#include "aubioext.h" #include "utils.h" /* settings */ diff --git a/examples/aubionotesmedian.c b/examples/aubionotesmedian.c index b59cff08..0cdc31d0 100644 --- a/examples/aubionotesmedian.c +++ b/examples/aubionotesmedian.c @@ -22,6 +22,7 @@ #include #include #include "aubio.h" +#include "aubioext.h" #include "utils.h" #include //required for FLOORF :( diff --git a/ext/midi/list.c b/ext/midi/list.c new file mode 100644 index 00000000..c95220cb --- /dev/null +++ b/ext/midi/list.c @@ -0,0 +1,256 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* Modified by the GLib Team and others 1997-1999. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#include "aubio_priv.h" +#include "list.h" + + + +aubio_list_t* +new_aubio_list(void) +{ + aubio_list_t* list; + list = AUBIO_NEW(aubio_list_t); + list->data = NULL; + list->next = NULL; + return list; +} + +void +del_aubio_list(aubio_list_t *list) +{ + aubio_list_t *next; + while (list) { + next = list->next; + AUBIO_FREE(list); + list = next; + } +} + +void +del_aubio_list1(aubio_list_t *list) +{ + if (list) { + AUBIO_FREE(list); + } +} + +aubio_list_t* +aubio_list_append(aubio_list_t *list, void* data) +{ + aubio_list_t *new_list; + aubio_list_t *last; + + new_list = new_aubio_list(); + new_list->data = data; + + if (list) + { + last = aubio_list_last(list); + /* g_assert (last != NULL); */ + last->next = new_list; + + return list; + } + else + return new_list; +} + +aubio_list_t* +aubio_list_prepend(aubio_list_t *list, void* data) +{ + aubio_list_t *new_list; + + new_list = new_aubio_list(); + new_list->data = data; + new_list->next = list; + + return new_list; +} + +aubio_list_t* +aubio_list_nth(aubio_list_t *list, int n) +{ + while ((n-- > 0) && list) { + list = list->next; + } + + return list; +} + +aubio_list_t* +aubio_list_remove(aubio_list_t *list, void* data) +{ + aubio_list_t *tmp; + aubio_list_t *prev; + + prev = NULL; + tmp = list; + + while (tmp) { + if (tmp->data == data) { + if (prev) { + prev->next = tmp->next; + } + if (list == tmp) { + list = list->next; + } + tmp->next = NULL; + del_aubio_list(tmp); + + break; + } + + prev = tmp; + tmp = tmp->next; + } + + return list; +} + +aubio_list_t* +aubio_list_remove_link(aubio_list_t *list, aubio_list_t *link) +{ + aubio_list_t *tmp; + aubio_list_t *prev; + + prev = NULL; + tmp = list; + + while (tmp) { + if (tmp == link) { + if (prev) { + prev->next = tmp->next; + } + if (list == tmp) { + list = list->next; + } + tmp->next = NULL; + break; + } + + prev = tmp; + tmp = tmp->next; + } + + return list; +} + +static aubio_list_t* +aubio_list_sort_merge(aubio_list_t *l1, aubio_list_t *l2, aubio_compare_func_t compare_func) +{ + aubio_list_t list, *l; + + l = &list; + + while (l1 && l2) { + if (compare_func(l1->data,l2->data) < 0) { + l = l->next = l1; + l1 = l1->next; + } else { + l = l->next = l2; + l2 = l2->next; + } + } + l->next= l1 ? l1 : l2; + + return list.next; +} + +aubio_list_t* +aubio_list_sort(aubio_list_t *list, aubio_compare_func_t compare_func) +{ + aubio_list_t *l1, *l2; + + if (!list) { + return NULL; + } + if (!list->next) { + return list; + } + + l1 = list; + l2 = list->next; + + while ((l2 = l2->next) != NULL) { + if ((l2 = l2->next) == NULL) + break; + l1=l1->next; + } + l2 = l1->next; + l1->next = NULL; + + return aubio_list_sort_merge(aubio_list_sort(list, compare_func), + aubio_list_sort(l2, compare_func), + compare_func); +} + + +aubio_list_t* +aubio_list_last(aubio_list_t *list) +{ + if (list) { + while (list->next) + list = list->next; + } + + return list; +} + +int +aubio_list_size(aubio_list_t *list) +{ + int n = 0; + while (list) { + n++; + list = list->next; + } + return n; +} + +aubio_list_t* aubio_list_insert_at(aubio_list_t *list, int n, void* data) +{ + aubio_list_t *new_list; + aubio_list_t *cur; + aubio_list_t *prev = NULL; + + new_list = new_aubio_list(); + new_list->data = data; + + cur = list; + while ((n-- > 0) && cur) { + prev = cur; + cur = cur->next; + } + + new_list->next = cur; + + if (prev) { + prev->next = new_list; + return list; + } else { + return new_list; + } +} diff --git a/ext/midi/list.h b/ext/midi/list.h new file mode 100644 index 00000000..3bcefd6a --- /dev/null +++ b/ext/midi/list.h @@ -0,0 +1,63 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * \file + * list of objects + * + * implement common list structure and its various functions + * + * adapted for audio by Paul Brossier + * + * Modified by the GLib Team and others 1997-1999. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#ifndef _AUBIO_LIST_H +#define _AUBIO_LIST_H + +typedef struct _aubio_list_t aubio_list_t; + +struct _aubio_list_t +{ + void* data; + aubio_list_t *next; +}; + +typedef int (*aubio_compare_func_t)(void* a, void* b); + +aubio_list_t* new_aubio_list(void); +void del_aubio_list(aubio_list_t *list); +void del_aubio_list1(aubio_list_t *list); +aubio_list_t* aubio_list_sort(aubio_list_t *list, aubio_compare_func_t compare_func); +aubio_list_t* aubio_list_append(aubio_list_t *list, void* data); +aubio_list_t* aubio_list_prepend(aubio_list_t *list, void* data); +aubio_list_t* aubio_list_remove(aubio_list_t *list, void* data); +aubio_list_t* aubio_list_remove_link(aubio_list_t *list, aubio_list_t *llink); +aubio_list_t* aubio_list_nth(aubio_list_t *list, int n); +aubio_list_t* aubio_list_last(aubio_list_t *list); +aubio_list_t* aubio_list_insert_at(aubio_list_t *list, int n, void* data); +int aubio_list_size(aubio_list_t *list); + +#define aubio_list_next(slist) ((slist) ? (((aubio_list_t *)(slist))->next) : NULL) +#define aubio_list_get(slist) ((slist) ? ((slist)->data) : NULL) + +#endif /* _AUBIO_LIST_H */ diff --git a/ext/midi/midi.c b/ext/midi/midi.c new file mode 100644 index 00000000..6a6c3708 --- /dev/null +++ b/ext/midi/midi.c @@ -0,0 +1,32 @@ +/* + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA + */ + +/* this file originally taken from FluidSynth - A Software Synthesizer + * Copyright (C) 2003 Peter Hanappe and others. + */ + +#include "aubio_priv.h" +#include "midi.h" +#include "midi_event.h" +#include "midi_track.h" +#include "midi_player.h" + +/* all outgoing user messages are stored in a global text buffer */ +#define MIDI_MESSAGE_LENGTH 1024 +char midi_message_buffer[MIDI_MESSAGE_LENGTH]; + diff --git a/ext/midi/midi.h b/ext/midi/midi.h new file mode 100644 index 00000000..4aaea597 --- /dev/null +++ b/ext/midi/midi.h @@ -0,0 +1,190 @@ +/* + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA + */ + +/* this file originally taken from fluidsynth, peter hanappe and others, + * adapted for aubio by paul brossier, + */ + + +/** \file + * midi header + * + * contains all (?) possible known midi messages. + * + * this file originally taken from fluidsynth, Peter Hanappe and others, + * adapted for aubio by Paul Brossier, + */ + +#ifndef _AUBIO_MIDI_H +#define _AUBIO_MIDI_H + +//typedef struct _aubio_midi_driver_t aubio_midi_driver_t; + +//int aubio_midi_send_event(aubio_synth_t* synth, aubio_player_t* player, aubio_midi_event_t* evt); + +//int aubio_midi_router_send_event(aubio_midi_router_t* router, aubio_midi_event_t* event); + + +/*************************************************************** + * + * CONSTANTS & ENUM + */ + +#ifdef __cplusplus +extern "C" { +#endif + +enum aubio_midi_event_type { + /* channel messages */ + NOTE_OFF = 0x80, + NOTE_ON = 0x90, + KEY_PRESSURE = 0xa0, + CONTROL_CHANGE = 0xb0, + PROGRAM_CHANGE = 0xc0, + CHANNEL_PRESSURE = 0xd0, + PITCH_BEND = 0xe0, + /* system exclusive */ + MIDI_SYSEX = 0xf0, + /* system common - never in midi files */ + MIDI_TIME_CODE = 0xf1, + MIDI_SONG_POSITION = 0xf2, + MIDI_SONG_SELECT = 0xf3, + MIDI_TUNE_REQUEST = 0xf6, + MIDI_EOX = 0xf7, + /* system real-time - never in midi files */ + MIDI_SYNC = 0xf8, + MIDI_TICK = 0xf9, + MIDI_START = 0xfa, + MIDI_CONTINUE = 0xfb, + MIDI_STOP = 0xfc, + MIDI_ACTIVE_SENSING = 0xfe, + MIDI_SYSTEM_RESET = 0xff, + /* meta event - for midi files only */ + MIDI_META_EVENT = 0xff +}; + +enum aubio_midi_control_change { + BANK_SELECT_MSB = 0x00, + MODULATION_MSB = 0x01, + BREATH_MSB = 0x02, + FOOT_MSB = 0x04, + PORTAMENTO_TIME_MSB = 0x05, + DATA_ENTRY_MSB = 0x06, + VOLUME_MSB = 0x07, + BALANCE_MSB = 0x08, + PAN_MSB = 0x0A, + EXPRESSION_MSB = 0x0B, + EFFECTS1_MSB = 0x0C, + EFFECTS2_MSB = 0x0D, + GPC1_MSB = 0x10, /* general purpose controller */ + GPC2_MSB = 0x11, + GPC3_MSB = 0x12, + GPC4_MSB = 0x13, + BANK_SELECT_LSB = 0x20, + MODULATION_WHEEL_LSB = 0x21, + BREATH_LSB = 0x22, + FOOT_LSB = 0x24, + PORTAMENTO_TIME_LSB = 0x25, + DATA_ENTRY_LSB = 0x26, + VOLUME_LSB = 0x27, + BALANCE_LSB = 0x28, + PAN_LSB = 0x2A, + EXPRESSION_LSB = 0x2B, + EFFECTS1_LSB = 0x2C, + EFFECTS2_LSB = 0x2D, + GPC1_LSB = 0x30, + GPC2_LSB = 0x31, + GPC3_LSB = 0x32, + GPC4_LSB = 0x33, + SUSTAIN_SWITCH = 0x40, + PORTAMENTO_SWITCH = 0x41, + SOSTENUTO_SWITCH = 0x42, + SOFT_PEDAL_SWITCH = 0x43, + LEGATO_SWITCH = 0x45, + HOLD2_SWITCH = 0x45, + SOUND_CTRL1 = 0x46, + SOUND_CTRL2 = 0x47, + SOUND_CTRL3 = 0x48, + SOUND_CTRL4 = 0x49, + SOUND_CTRL5 = 0x4A, + SOUND_CTRL6 = 0x4B, + SOUND_CTRL7 = 0x4C, + SOUND_CTRL8 = 0x4D, + SOUND_CTRL9 = 0x4E, + SOUND_CTRL10 = 0x4F, + GPC5 = 0x50, + GPC6 = 0x51, + GPC7 = 0x52, + GPC8 = 0x53, + PORTAMENTO_CTRL = 0x54, + EFFECTS_DEPTH1 = 0x5B, + EFFECTS_DEPTH2 = 0x5C, + EFFECTS_DEPTH3 = 0x5D, + EFFECTS_DEPTH4 = 0x5E, + EFFECTS_DEPTH5 = 0x5F, + DATA_ENTRY_INCR = 0x60, + DATA_ENTRY_DECR = 0x61, + NRPN_LSB = 0x62, + NRPN_MSB = 0x63, + RPN_LSB = 0x64, + RPN_MSB = 0x65, + ALL_SOUND_OFF = 0x78, + ALL_CTRL_OFF = 0x79, + LOCAL_CONTROL = 0x7A, + ALL_NOTES_OFF = 0x7B, + OMNI_OFF = 0x7C, + OMNI_ON = 0x7D, + POLY_OFF = 0x7E, + POLY_ON = 0x7F +}; + +enum midi_meta_event { + MIDI_COPYRIGHT = 0x02, + MIDI_TRACK_NAME = 0x03, + MIDI_INST_NAME = 0x04, + MIDI_LYRIC = 0x05, + MIDI_MARKER = 0x06, + MIDI_CUE_POINT = 0x07, + MIDI_EOT = 0x2f, + MIDI_SET_TEMPO = 0x51, + MIDI_SMPTE_OFFSET = 0x54, + MIDI_TIME_SIGNATURE = 0x58, + MIDI_KEY_SIGNATURE = 0x59, + MIDI_SEQUENCER_EVENT = 0x7f +}; + +enum aubio_player_status +{ + AUBIO_MIDI_PLAYER_READY, + AUBIO_MIDI_PLAYER_PLAYING, + AUBIO_MIDI_PLAYER_DONE +}; + +enum aubio_driver_status +{ + AUBIO_MIDI_READY, + AUBIO_MIDI_LISTENING, + AUBIO_MIDI_DONE +}; + +#ifdef __cplusplus +} +#endif + +#endif /* _AUBIO_MIDI_H */ diff --git a/ext/midi/midi_alsa_raw.c b/ext/midi/midi_alsa_raw.c new file mode 100644 index 00000000..1556d018 --- /dev/null +++ b/ext/midi/midi_alsa_raw.c @@ -0,0 +1,308 @@ +/* + * Copyright 2004 Paul Brossier + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA + */ + +/* this file originally taken from Fluidsynth, Peter Hanappe and others. */ + +/** \file + * Midi driver for the Advanced Linux Sound Architecture + */ + + +#include "aubio_priv.h" +#include "midi.h" +#include "midi_event.h" +#include "midi_parser.h" +#include "midi_driver.h" + +#if ALSA_SUPPORT + +#define ALSA_PCM_NEW_HW_PARAMS_API +#include +#include +#include +#include +#include +/* #include //perror is in stdio.h */ + +#include "config.h" + +#define AUBIO_ALSA_DEFAULT_MIDI_DEVICE "default" + +/** \bug double define? */ +#define AUBIO_ALSA_BUFFER_LENGTH 512 + +/* SCHED_FIFO priorities for ALSA threads (see pthread_attr_setschedparam) */ +#define ALSA_RAWMIDI_SCHED_PRIORITY 90 +#define ALSA_SEQ_SCHED_PRIORITY 90 + +/** aubio_midi_alsa_raw_driver_t */ +typedef struct { + aubio_midi_driver_t driver; + snd_rawmidi_t *rawmidi_in; + snd_rawmidi_t *rawmidi_out; + struct pollfd *pfd; + int npfd; + pthread_t thread; + int status; + unsigned char buffer[AUBIO_ALSA_BUFFER_LENGTH]; + aubio_midi_parser_t* parser; +} aubio_midi_alsa_raw_driver_t; + +aubio_midi_driver_t* new_aubio_midi_alsa_raw_driver(//aubio_settings_t* settings, + handle_midi_event_func_t handler, + void* event_handler_data); +int del_aubio_midi_alsa_raw_driver(aubio_midi_driver_t* p); +static void* aubio_midi_alsa_raw_run(void* d); + + +/************************************************************** + * + * Alsa MIDI driver + * + */ + +//void aubio_midi_alsa_raw_driver_settings(aubio_settings_t* settings) +//{ +// aubio_settings_register_str(settings, "midi.alsa.device", "default", 0, NULL, NULL); +//} + +/** new_aubio_midi_alsa_raw_driver */ +aubio_midi_driver_t* new_aubio_midi_alsa_raw_driver( + //aubio_settings_t* settings, + handle_midi_event_func_t handler, + void* data) +{ + int i, err; + aubio_midi_alsa_raw_driver_t* dev; + pthread_attr_t attr; + int sched = SCHED_FIFO; + struct sched_param priority; + int count; + struct pollfd *pfd = NULL; + char* device = NULL; + + /* not much use doing anything */ + if (handler == NULL) { + AUBIO_ERR("Invalid argument"); + return NULL; + } + + /* allocate the device */ + dev = AUBIO_NEW(aubio_midi_alsa_raw_driver_t); + if (dev == NULL) { + AUBIO_ERR( "Out of memory"); + return NULL; + } + AUBIO_MEMSET(dev, 0, sizeof(aubio_midi_alsa_raw_driver_t)); + + dev->driver.handler = handler; + dev->driver.data = data; + + /* allocate one event to store the input data */ + dev->parser = new_aubio_midi_parser(); + if (dev->parser == NULL) { + AUBIO_ERR( "Out of memory"); + goto error_recovery; + } + + /* get the device name. if none is specified, use the default device. */ + //aubio_settings_getstr(settings, "midi.alsa.device", &device); + if (device == NULL) { + device = "default"; + } + + /* open the hardware device. only use midi in. */ + if ((err = snd_rawmidi_open(&dev->rawmidi_in, NULL, device, SND_RAWMIDI_NONBLOCK)) < 0) { + //if ((err = snd_rawmidi_open(&dev->rawmidi_in, &dev->rawmidi_out, device, SND_RAWMIDI_NONBLOCK)) < 0) { + AUBIO_ERR( "Error opening ALSA raw MIDI IN port"); + goto error_recovery; + } + + /* get # of MIDI file descriptors */ + count = snd_rawmidi_poll_descriptors_count(dev->rawmidi_in); + if (count > 0) { /* make sure there are some */ + pfd = AUBIO_MALLOC(sizeof (struct pollfd) * count); + dev->pfd = AUBIO_MALLOC(sizeof (struct pollfd) * count); + /* grab file descriptor POLL info structures */ + count = snd_rawmidi_poll_descriptors(dev->rawmidi_in, pfd, count); + } + + /* copy the input FDs */ + for (i = 0; i < count; i++) { /* loop over file descriptors */ + if (pfd[i].events & POLLIN) { /* use only the input FDs */ + dev->pfd[dev->npfd].fd = pfd[i].fd; + dev->pfd[dev->npfd].events = POLLIN; + dev->pfd[dev->npfd].revents = 0; + dev->npfd++; + } + } + AUBIO_FREE(pfd); + + + + dev->status = AUBIO_MIDI_READY; + + /* create the midi thread */ + if (pthread_attr_init(&attr)) { + AUBIO_ERR( "Couldn't initialize midi thread attributes"); + goto error_recovery; + } + + /* Was: "use fifo scheduling. if it fails, use default scheduling." */ + /* Now normal scheduling is used by default for the MIDI thread. The reason is, + * that fluidsynth works better with low latencies under heavy load, if only the + * audio thread is prioritized. + * With MIDI at ordinary priority, that could result in individual notes being played + * a bit late. On the other hand, if the audio thread is delayed, an audible dropout + * is the result. + * To reproduce this: Edirol UA-1 USB-MIDI interface, four buffers + * with 45 samples each (roughly 4 ms latency), ravewave soundfont. -MN + */ + + /* Not so sure anymore. We're losing MIDI data, if we can't keep up with + * the speed it is generated. */ + /* AUBIO_MSG("Note: High-priority scheduling for the MIDI thread was intentionally disabled."); + sched=SCHED_OTHER;*/ + + while (1) { + err = pthread_attr_setschedpolicy(&attr, sched); + if (err) { + //AUBIO_LOG(AUBIO_WARN, "Couldn't set high priority scheduling for the MIDI input"); + AUBIO_MSG( "Couldn't set high priority scheduling for the MIDI input"); + if (sched == SCHED_FIFO) { + sched = SCHED_OTHER; + continue; + } else { + AUBIO_ERR( "Couldn't set scheduling policy."); + goto error_recovery; + } + } + + /* SCHED_FIFO will not be active without setting the priority */ + priority.sched_priority = (sched == SCHED_FIFO) ? + ALSA_RAWMIDI_SCHED_PRIORITY : 0; + pthread_attr_setschedparam (&attr, &priority); + err = pthread_create(&dev->thread, &attr, aubio_midi_alsa_raw_run, (void*) dev); + if (err) { + AUBIO_MSG( "Couldn't set high priority scheduling for the MIDI input"); + if (sched == SCHED_FIFO) { + sched = SCHED_OTHER; + continue; + } else { + AUBIO_ERR( "Couldn't create the midi thread."); + goto error_recovery; + } + } + break; + } + return (aubio_midi_driver_t*) dev; + +error_recovery: + del_aubio_midi_alsa_raw_driver((aubio_midi_driver_t*) dev); + return NULL; + +} + +/** del_aubio_midi_alsa_raw_driver */ +int del_aubio_midi_alsa_raw_driver(aubio_midi_driver_t* p) +{ + aubio_midi_alsa_raw_driver_t* dev; + + dev = (aubio_midi_alsa_raw_driver_t*) p; + if (dev == NULL) { + return AUBIO_OK; + } + + dev->status = AUBIO_MIDI_DONE; + + /* cancel the thread and wait for it before cleaning up */ + if (dev->thread) { + if (pthread_cancel(dev->thread)) { + AUBIO_ERR( "Failed to cancel the midi thread"); + return AUBIO_FAIL; + } + if (pthread_join(dev->thread, NULL)) { + AUBIO_ERR( "Failed to join the midi thread"); + return AUBIO_FAIL; + } + } + if (dev->rawmidi_in) { + snd_rawmidi_drain(dev->rawmidi_in); + snd_rawmidi_close(dev->rawmidi_in); + } + if (dev->rawmidi_out) { + snd_rawmidi_drain(dev->rawmidi_out); + snd_rawmidi_close(dev->rawmidi_in); + } + if (dev->parser != NULL) { + del_aubio_midi_parser(dev->parser); + } + AUBIO_FREE(dev); + return AUBIO_OK; +} + +/** aubio_midi_alsa_raw_run */ +void * aubio_midi_alsa_raw_run(void* d) +{ + int n, i; + aubio_midi_event_t* evt; + aubio_midi_alsa_raw_driver_t* dev = (aubio_midi_alsa_raw_driver_t*) d; + + /* make sure the other threads can cancel this thread any time */ + if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL)) { + AUBIO_ERR( "Failed to set the cancel state of the midi thread"); + pthread_exit(NULL); + } + if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) { + AUBIO_ERR( "Failed to set the cancel state of the midi thread"); + pthread_exit(NULL); + } + + /* go into a loop until someone tells us to stop */ + dev->status = AUBIO_MIDI_LISTENING; + while (dev->status == AUBIO_MIDI_LISTENING) { + + /* is there something to read? */ + /* use a 100 milliseconds timeout */ + n = poll(dev->pfd, dev->npfd, 100); + if (n < 0) { + perror("poll"); + } else if (n > 0) { + + /* read new data */ + n = snd_rawmidi_read(dev->rawmidi_in, dev->buffer, + AUBIO_ALSA_BUFFER_LENGTH); + if ((n < 0) && (n != -EAGAIN)) { + AUBIO_ERR( "Failed to read the midi input"); + dev->status = AUBIO_MIDI_DONE; + } + + /* let the parser convert the data into events */ + for (i = 0; i < n; i++) { + evt = aubio_midi_parser_parse(dev->parser, dev->buffer[i]); + if (evt != NULL) { + (*dev->driver.handler)(dev->driver.data, evt); + } + } + }; + } + pthread_exit(NULL); +} + +#endif /* #if ALSA_SUPPORT */ diff --git a/ext/midi/midi_alsa_seq.c b/ext/midi/midi_alsa_seq.c new file mode 100644 index 00000000..cf556eb7 --- /dev/null +++ b/ext/midi/midi_alsa_seq.c @@ -0,0 +1,419 @@ +/* + * Copyright 2004 Paul Brossier + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA + */ + +/* this file originally taken from Fluidsynth, Peter Hanappe and others. */ + +/** \file + * Midi driver for the Advanced Linux Sound Architecture (sequencer mode) + */ + + +#include "aubio_priv.h" +#include "midi.h" +#include "midi_event.h" +#include "midi_parser.h" +#include "midi_driver.h" +#include "config.h" + +#if ALSA_SUPPORT + +#define ALSA_PCM_NEW_HW_PARAMS_API +#include +#include +#include +#include +#include +/* #include //perror is in stdio.h */ + +#define AUBIO_ALSA_DEFAULT_SEQ_DEVICE "default" + +#define AUBIO_ALSA_BUFFER_LENGTH 512 + +/* SCHED_FIFO priorities for ALSA threads (see pthread_attr_setschedparam) */ +#define ALSA_RAWMIDI_SCHED_PRIORITY 90 +#define ALSA_SEQ_SCHED_PRIORITY 90 + + +/** aubio_alsa_seq_driver_t */ +typedef struct { + aubio_midi_driver_t driver; + snd_seq_t *seq_handle; + int seq_port; + struct pollfd *pfd; + int npfd; + pthread_t thread; + int status; +} aubio_alsa_seq_driver_t; + +aubio_midi_driver_t* new_aubio_alsa_seq_driver(//aubio_settings_t* settings, + handle_midi_event_func_t handler, + void* data); +int del_aubio_alsa_seq_driver(aubio_midi_driver_t* p); +static void* aubio_alsa_seq_run(void* d); + +//void aubio_alsa_seq_driver_settings(aubio_settings_t* settings) +//{ +// aubio_settings_register_str(settings, "midi.alsa_seq.device", "default", 0, NULL, NULL); +// aubio_settings_register_str(settings, "midi.alsa_seq.id", "pid", 0, NULL, NULL); +//} + +/** new_aubio_alsa_seq_driver */ +aubio_midi_driver_t* new_aubio_alsa_seq_driver(//aubio_settings_t* settings, + handle_midi_event_func_t handler, void* data) +{ + int i, err; + aubio_alsa_seq_driver_t* dev; /**< object to return */ + pthread_attr_t attr; /**< sequencer thread */ + int sched = SCHED_FIFO; /**< default scheduling policy */ + struct sched_param priority; /**< scheduling priority settings */ + int count; /**< number of MIDI file descriptors */ + struct pollfd *pfd = NULL; /**< poll file descriptor array (copied in dev->pfd) */ + char* device = NULL; /**< the device name */ + char* id = NULL; + char full_id[64]; + char full_name[64]; + + /* not much use doing anything */ + if (handler == NULL) { + AUBIO_ERR( "Invalid argument"); + return NULL; + } + + /* allocate the device */ + dev = AUBIO_NEW(aubio_alsa_seq_driver_t); + if (dev == NULL) { + AUBIO_ERR( "Out of memory"); + return NULL; + } + AUBIO_MEMSET(dev, 0, sizeof(aubio_alsa_seq_driver_t)); + dev->seq_port = -1; + dev->driver.data = data; + dev->driver.handler = handler; + + /* get the device name. if none is specified, use the default device. */ + //aubio_settings_getstr(settings, "midi.alsa_seq.device", &device); + if (device == NULL) { + device = "default"; + } + + /* open the sequencer INPUT only, non-blocking */ + //if ((err = snd_seq_open(&dev->seq_handle, device, SND_SEQ_OPEN_INPUT, + if ((err = snd_seq_open(&dev->seq_handle, device, SND_SEQ_OPEN_DUPLEX, + SND_SEQ_NONBLOCK)) < 0) { + AUBIO_ERR( "Error opening ALSA sequencer"); + goto error_recovery; + } + + /* tell the ladcca server our client id */ +#ifdef LADCCA_SUPPORT + { + int enable_ladcca = 1; + //aubio_settings_getint (settings, "ladcca.enable", &enable_ladcca); + if (enable_ladcca) + cca_alsa_client_id (aubio_cca_client, snd_seq_client_id (dev->seq_handle)); + } +#endif /* LADCCA_SUPPORT */ + + /* get # of MIDI file descriptors */ + count = snd_seq_poll_descriptors_count(dev->seq_handle, POLLIN); + if (count > 0) { /* make sure there are some */ + pfd = AUBIO_MALLOC(sizeof (struct pollfd) * count); + dev->pfd = AUBIO_MALLOC(sizeof (struct pollfd) * count); + /* grab file descriptor POLL info structures */ + count = snd_seq_poll_descriptors(dev->seq_handle, pfd, count, POLLIN); + } + + for (i = 0; i < count; i++) { /* loop over file descriptors */ + /* copy the input FDs */ + if (pfd[i].events & POLLIN) { /* use only the input FDs */ + dev->pfd[dev->npfd].fd = pfd[i].fd; + dev->pfd[dev->npfd].events = POLLIN; + dev->pfd[dev->npfd].revents = 0; + dev->npfd++; + } + } + AUBIO_FREE(pfd); + + //aubio_settings_getstr(settings, "midi.alsa_seq.id", &id); + + if (id != NULL) { + if (AUBIO_STRCMP(id, "pid") == 0) { + snprintf(full_id, 64, "aubio (%d)", getpid()); + snprintf(full_name, 64, "aubio_port (%d)", getpid()); + } else { + snprintf(full_id, 64, "aubio (%s)", id); + snprintf(full_name, 64, "aubio_port (%s)", id); + } + } else { + snprintf(full_id, 64, "aubio"); + snprintf(full_name, 64, "aubio_port"); + } + + /* set the client name */ + snd_seq_set_client_name (dev->seq_handle, full_id); + + if ((dev->seq_port = snd_seq_create_simple_port (dev->seq_handle, + full_name, + SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE | + SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ | + SND_SEQ_PORT_CAP_DUPLEX, + SND_SEQ_PORT_TYPE_APPLICATION)) < 0) + { + AUBIO_ERR( "Error creating ALSA sequencer port"); + goto error_recovery; + } + + dev->status = AUBIO_MIDI_READY; + + /* create the midi thread */ + if (pthread_attr_init(&attr)) { + AUBIO_ERR( "Couldn't initialize midi thread attributes"); + goto error_recovery; + } + + /* use fifo scheduling. if it fails, use default scheduling. */ + while (1) { + err = pthread_attr_setschedpolicy(&attr, sched); + if (err) { + AUBIO_MSG( "Couldn't set high priority scheduling for the MIDI input"); + if (sched == SCHED_FIFO) { + sched = SCHED_OTHER; + continue; + } else { + AUBIO_ERR( "Couldn't set scheduling policy."); + goto error_recovery; + } + } + + /* SCHED_FIFO will not be active without setting the priority */ + priority.sched_priority = (sched == SCHED_FIFO) ? ALSA_SEQ_SCHED_PRIORITY : 0; + pthread_attr_setschedparam (&attr, &priority); + + err = pthread_create(&dev->thread, &attr, aubio_alsa_seq_run, (void*) dev); + if (err) { + AUBIO_ERR( "Couldn't set high priority scheduling for the MIDI input"); + if (sched == SCHED_FIFO) { + sched = SCHED_OTHER; + continue; + } else { + //AUBIO_LOG(AUBIO_PANIC, "Couldn't create the midi thread."); + AUBIO_ERR( "Couldn't create the midi thread."); + goto error_recovery; + } + } + break; + } + return (aubio_midi_driver_t*) dev; + + +error_recovery: + del_aubio_alsa_seq_driver((aubio_midi_driver_t*) dev); + return NULL; +} + +/** del_aubio_alsa_seq_driver */ +int del_aubio_alsa_seq_driver(aubio_midi_driver_t* p) +{ + aubio_alsa_seq_driver_t* dev; + + dev = (aubio_alsa_seq_driver_t*) p; + if (dev == NULL) { + return AUBIO_OK; + } + + dev->status = AUBIO_MIDI_DONE; + + /* cancel the thread and wait for it before cleaning up */ + if (dev->thread) { + if (pthread_cancel(dev->thread)) { + AUBIO_ERR( "Failed to cancel the midi thread"); + return AUBIO_FAIL; + } + if (pthread_join(dev->thread, NULL)) { + AUBIO_ERR( "Failed to join the midi thread"); + return AUBIO_FAIL; + } + } + if (dev->seq_port >= 0) { + snd_seq_delete_simple_port (dev->seq_handle, dev->seq_port); + } + if (dev->seq_handle) { + snd_seq_drain_output(dev->seq_handle); + snd_seq_close(dev->seq_handle); + } + AUBIO_FREE(dev); + return AUBIO_OK; +} + +/** aubio_alsa_seq_run */ +void* aubio_alsa_seq_run(void* d) +{ + int n;//, i; + snd_seq_event_t *seq_ev; + aubio_midi_event_t evt; + aubio_alsa_seq_driver_t* dev = (aubio_alsa_seq_driver_t*) d; + + /* make sure the other threads can cancel this thread any time */ + if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL)) { + AUBIO_ERR( "Failed to set the cancel state of the midi thread"); + pthread_exit(NULL); + } + if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) { + AUBIO_ERR( "Failed to set the cancel state of the midi thread"); + pthread_exit(NULL); + } + + /* go into a loop until someone tells us to stop */ + dev->status = AUBIO_MIDI_LISTENING; + while (dev->status == AUBIO_MIDI_LISTENING) { + + /* is there something to read? */ + n = poll(dev->pfd, dev->npfd, 1); /* use a 1 milliseconds timeout */ + if (n < 0) { + perror("poll"); + } else if (n > 0) { + + /* read new events from the midi input port */ + while ((n = snd_seq_event_input(dev->seq_handle, &seq_ev)) >= 0) + { + switch (seq_ev->type) + { + case SND_SEQ_EVENT_NOTEON: + evt.type = NOTE_ON; + evt.channel = seq_ev->data.note.channel; + evt.param1 = seq_ev->data.note.note; + evt.param2 = seq_ev->data.note.velocity; + break; + case SND_SEQ_EVENT_NOTEOFF: + evt.type = NOTE_OFF; + evt.channel = seq_ev->data.note.channel; + evt.param1 = seq_ev->data.note.note; + evt.param2 = seq_ev->data.note.velocity; + break; + case SND_SEQ_EVENT_KEYPRESS: + evt.type = KEY_PRESSURE; + evt.channel = seq_ev->data.note.channel; + evt.param1 = seq_ev->data.note.note; + evt.param2 = seq_ev->data.note.velocity; + break; + case SND_SEQ_EVENT_CONTROLLER: + evt.type = CONTROL_CHANGE; + evt.channel = seq_ev->data.control.channel; + evt.param1 = seq_ev->data.control.param; + evt.param2 = seq_ev->data.control.value; + break; + case SND_SEQ_EVENT_PITCHBEND: + evt.type = PITCH_BEND; + evt.channel = seq_ev->data.control.channel; + /* ALSA pitch bend is -8192 - 8191, we adjust it here */ + evt.param1 = seq_ev->data.control.value + 8192; + break; + case SND_SEQ_EVENT_PGMCHANGE: + evt.type = PROGRAM_CHANGE; + evt.channel = seq_ev->data.control.channel; + evt.param1 = seq_ev->data.control.value; + break; + case SND_SEQ_EVENT_CHANPRESS: + evt.type = CHANNEL_PRESSURE; + evt.channel = seq_ev->data.control.channel; + evt.param1 = seq_ev->data.control.value; + break; + default: + continue; /* unhandled event, next loop iteration */ + } + + /* send the events to the next link in the chain */ + (*dev->driver.handler)(dev->driver.data, &evt); + + /* dump input on output */ + //snd_seq_ev_set_source(new_ev, dev->seq_port); + //snd_seq_ev_set_dest(seq_ev,dev->seq_handle,dev->seq_client); + //snd_seq_ev_set_subs(new_ev); + //snd_seq_ev_set_direct(new_ev); + //snd_seq_event_output(dev->seq_handle, new_ev); + //snd_seq_drain_output(dev->seq_handle); + + } + } + + if ((n < 0) && (n != -EAGAIN)) { + AUBIO_ERR( "Error occured while reading ALSA sequencer events"); + dev->status = AUBIO_MIDI_DONE; + } + +// /* added by piem to handle new data to output */ +// while (/* get new data, but from where ??? (n = snd_seq_event_output(dev->seq_handle, seq_ev)) >= 0*/ ) +// { +// /* dump input on output */ +// snd_seq_ev_set_source(new_ev, dev->seq_port); +// //snd_seq_ev_set_dest(seq_ev,dev->seq_handle,dev->seq_client); +// snd_seq_ev_set_subs(new_ev); +// snd_seq_ev_set_direct(new_ev); +// snd_seq_event_output(dev->seq_handle, new_ev); +// snd_seq_drain_output(dev->seq_handle); +// } + + } + pthread_exit(NULL); +} + + +snd_seq_event_t ev; + +void aubio_midi_direct_output(aubio_midi_driver_t * d, aubio_midi_event_t * event) +{ + aubio_alsa_seq_driver_t* dev = (aubio_alsa_seq_driver_t*) d; + /* + if (pthread_join(dev->thread, NULL)) { + AUBIO_ERR( "Failed to join the midi thread"); + } + */ + switch(event->type) + { + case NOTE_ON: + ev.type = SND_SEQ_EVENT_NOTEON; + ev.data.note.channel = event->channel; + ev.data.note.note = event->param1; + ev.data.note.velocity = event->param2; + //AUBIO_ERR( "NOTE_ON %d\n", event->param1); + break; + case NOTE_OFF: + ev.type = SND_SEQ_EVENT_NOTEOFF; + ev.data.note.channel = event->channel; + ev.data.note.note = event->param1; + ev.data.note.velocity = event->param2; + //AUBIO_ERR( "NOTE_OFF %d\n", event->param1); + break; + default: + break; + } + if (ev.type == SND_SEQ_EVENT_NOTEOFF || ev.type == SND_SEQ_EVENT_NOTEON ) { + snd_seq_ev_set_subs(&ev); + snd_seq_ev_set_direct(&ev); + snd_seq_ev_set_source(&ev, dev->seq_port); + snd_seq_event_output_direct(dev->seq_handle, &ev); + } + /* + if (pthread_detach(dev->thread)) { + AUBIO_ERR( "Failed to leave the midi thread"); + } + */ +} + +#endif /* #if ALSA_SUPPORT */ diff --git a/ext/midi/midi_driver.c b/ext/midi/midi_driver.c new file mode 100644 index 00000000..c1c4de40 --- /dev/null +++ b/ext/midi/midi_driver.c @@ -0,0 +1,195 @@ +/* + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA + */ +/* This file originally tajke from + * FluidSynth - A Software Synthesizer + * + * Copyright (C) 2003 Peter Hanappe and others. + */ + +#include "aubio_priv.h" +#include "midi_event.h" +#include "midi_driver.h" +//#include "settings.h" + +/* + * aubio_mdriver_definition + */ +struct aubio_mdriver_definition_t { + char* name; + aubio_midi_driver_t* (*new)( + //aubio_settings_t* settings, + handle_midi_event_func_t event_handler, + void* event_handler_data); + int (*free)(aubio_midi_driver_t* p); + void (*settings)(aubio_settings_t* settings); +}; + + +/* ALSA */ +#if ALSA_SUPPORT +aubio_midi_driver_t* new_aubio_midi_alsa_raw_driver( + //aubio_settings_t* settings, + handle_midi_event_func_t handler, + void* event_handler_data); +int del_aubio_midi_alsa_raw_driver(aubio_midi_driver_t* p); +void aubio_midi_alsa_raw_driver_settings(aubio_settings_t* settings); + +aubio_midi_driver_t* new_aubio_alsa_seq_driver( + //aubio_settings_t* settings, + handle_midi_event_func_t handler, + void* event_handler_data); +int del_aubio_alsa_seq_driver(aubio_midi_driver_t* p); +void aubio_alsa_seq_driver_settings(aubio_settings_t* settings); +#endif + +/* OSS */ +#if OSS_SUPPORT +aubio_midi_driver_t* new_aubio_oss_midi_driver(aubio_settings_t* settings, + handle_midi_event_func_t handler, + void* event_handler_data); +int del_aubio_oss_midi_driver(aubio_midi_driver_t* p); +//void aubio_oss_midi_driver_settings(aubio_settings_t* settings); +#endif + +/* Windows MIDI service */ +#if WINMIDI_SUPPORT +aubio_midi_driver_t* new_aubio_winmidi_driver(aubio_settings_t* settings, + handle_midi_event_func_t handler, + void* event_handler_data); +int del_aubio_winmidi_driver(aubio_midi_driver_t* p); +#endif + +/* definitions for the MidiShare driver */ +#if MIDISHARE_SUPPORT +aubio_midi_driver_t* new_aubio_midishare_midi_driver(aubio_settings_t* settings, + handle_midi_event_func_t handler, + void* event_handler_data); +int del_aubio_midishare_midi_driver(aubio_midi_driver_t* p); +#endif + + +struct aubio_mdriver_definition_t aubio_midi_drivers[] = { +#if OSS_SUPPORT + { "oss", + new_aubio_oss_midi_driver, + del_aubio_oss_midi_driver, + aubio_oss_midi_driver_settings }, +#endif +#if ALSA_SUPPORT + { "alsa_raw", + new_aubio_midi_alsa_raw_driver, + del_aubio_midi_alsa_raw_driver, + NULL /*aubio_midi_alsa_raw_driver_settings*/ }, + { "alsa_seq", + new_aubio_alsa_seq_driver, + del_aubio_alsa_seq_driver, + NULL /*aubio_alsa_seq_driver_settings*/ }, +#endif +#if WINMIDI_SUPPORT + { "winmidi", + new_aubio_winmidi_driver, + del_aubio_winmidi_driver, + NULL }, +#endif +#if MIDISHARE_SUPPORT + { "midishare", + new_aubio_midishare_midi_driver, + del_aubio_midishare_midi_driver, + NULL }, +#endif + { NULL, NULL, NULL, NULL } +}; + + +void aubio_midi_driver_settings(aubio_settings_t* settings) +{ + int i; + +#if 0 + /* Set the default driver */ +#if ALSA_SUPPORT + aubio_settings_register_str(settings, "midi.driver", "alsa_seq", 0, NULL, NULL); +#elif OSS_SUPPORT + aubio_settings_register_str(settings, "midi.driver", "oss", 0, NULL, NULL); +#elif WINMIDI_SUPPORT + aubio_settings_register_str(settings, "midi.driver", "winmidi", 0, NULL, NULL); +#elif MIDISHARE_SUPPORT + aubio_settings_register_str(settings, "midi.driver", "midishare", 0, NULL, NULL); +#else + aubio_settings_register_str(settings, "midi.driver", "", 0, NULL, NULL); +#endif + + /* Add all drivers to the list of options */ +#if ALSA_SUPPORT + aubio_settings_add_option(settings, "midi.driver", "alsa_seq"); + aubio_settings_add_option(settings, "midi.driver", "alsa_raw"); +#endif +#if OSS_SUPPORT + aubio_settings_add_option(settings, "midi.driver", "oss"); +#endif +#if WINMIDI_SUPPORT + aubio_settings_add_option(settings, "midi.driver", "winmidi"); +#endif +#if MIDISHARE_SUPPORT + aubio_settings_add_option(settings, "midi.driver", "midishare"); +#endif + +#endif + + for (i = 0; aubio_midi_drivers[i].name != NULL; i++) { + if (aubio_midi_drivers[i].settings != NULL) { + aubio_midi_drivers[i].settings(settings); + } + } +} + +//aubio_midi_driver_t* new_aubio_midi_driver(aubio_settings_t* settings, +aubio_midi_driver_t* new_aubio_midi_driver(char * name, + handle_midi_event_func_t handler, + void* event_handler_data) +{ + int i; + aubio_midi_driver_t* driver = NULL; + for (i = 0; aubio_midi_drivers[i].name != NULL; i++) { + if (AUBIO_STRCMP(name,aubio_midi_drivers[i].name) == 0){ + //if (aubio_settings_str_equal(settings, "midi.driver", aubio_midi_drivers[i].name)) { + AUBIO_DBG( "Using '%s' midi driver\n", aubio_midi_drivers[i].name); + //driver = aubio_midi_drivers[i].new(settings, handler, event_handler_data); + driver = aubio_midi_drivers[i].new(/*name,*/ handler, event_handler_data); + if (driver) { + driver->name = aubio_midi_drivers[i].name; + } + return driver; + } + } + AUBIO_ERR("Couldn't find the requested midi driver"); + return NULL; +} + +void del_aubio_midi_driver(aubio_midi_driver_t* driver) +{ + int i; + + for (i = 0; aubio_midi_drivers[i].name != NULL; i++) { + if (aubio_midi_drivers[i].name == driver->name) { + aubio_midi_drivers[i].free(driver); + return; + } + } +} + diff --git a/ext/midi/midi_driver.h b/ext/midi/midi_driver.h new file mode 100644 index 00000000..f9a0e7ae --- /dev/null +++ b/ext/midi/midi_driver.h @@ -0,0 +1,57 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA + */ + +/* this file orginally taken from : + * FluidSynth - A Software Synthesizer + * Copyright (C) 2003 Peter Hanappe and others. + */ + + +/** \file + * generic midi driver + */ + +#ifndef _AUBIO_MDRIVER_H +#define _AUBIO_MDRIVER_H + +typedef void aubio_settings_t; + +typedef int (*handle_midi_event_func_t)(void* data, aubio_midi_event_t* event); + +/** aubio_midi_driver_t */ +typedef struct _aubio_midi_driver_t aubio_midi_driver_t; + +struct _aubio_midi_driver_t +{ + char* name; + handle_midi_event_func_t handler; + void* data; +}; + +//aubio_midi_driver_t* new_aubio_midi_driver(aubio_settings_t* settings, +aubio_midi_driver_t* new_aubio_midi_driver(char * name, + handle_midi_event_func_t handler, + void* event_handler_data); +void del_aubio_midi_driver(aubio_midi_driver_t* driver); +void aubio_midi_driver_settings(aubio_settings_t* settings); + +#include "config.h" +#if JACK_SUPPORT +void aubio_midi_direct_output(aubio_midi_driver_t * dev, aubio_midi_event_t * event); +#endif + +#endif /* _AUBIO_AUDRIVER_H */ diff --git a/ext/midi/midi_event.c b/ext/midi/midi_event.c new file mode 100644 index 00000000..ae5bb8a1 --- /dev/null +++ b/ext/midi/midi_event.c @@ -0,0 +1,222 @@ +/* + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA + */ + +/* this file originally taken from FluidSynth - A Software Synthesizer + * Copyright (C) 2003 Peter Hanappe and others. + */ + +#include "aubio_priv.h" +#include "midi_event.h" +#include "midi.h" + +/****************************************************** + * + * aubio_event_t + */ + +/* + * new_aubio_midi_event + */ +aubio_midi_event_t* new_aubio_midi_event() +{ + aubio_midi_event_t* evt; + evt = AUBIO_NEW(aubio_midi_event_t); + if (evt == NULL) { + AUBIO_ERR( "Out of memory"); + return NULL; + } + evt->dtime = 0; + evt->type = 0; + evt->channel = 0; + evt->param1 = 0; + evt->param2 = 0; + evt->next = NULL; + return evt; +} + +/** del_aubio_midi_event */ +int del_aubio_midi_event(aubio_midi_event_t* evt) +{ + aubio_midi_event_t *temp; + while(evt) + { + temp = evt->next; + AUBIO_FREE(evt); + evt = temp; + } + return AUBIO_OK; +} + +/* + * aubio_midi_event_get_type + */ +int aubio_midi_event_get_type(aubio_midi_event_t* evt) +{ + return evt->type; +} + +/* + * aubio_midi_event_set_type + */ +int aubio_midi_event_set_type(aubio_midi_event_t* evt, int type) +{ + evt->type = type; + return AUBIO_OK; +} + +/* + * aubio_midi_event_get_channel + */ +int aubio_midi_event_get_channel(aubio_midi_event_t* evt) +{ + return evt->channel; +} + +/* + * aubio_midi_event_set_channel + */ +int aubio_midi_event_set_channel(aubio_midi_event_t* evt, int chan) +{ + evt->channel = chan; + return AUBIO_OK; +} + +/* + * aubio_midi_event_get_key + */ +int aubio_midi_event_get_key(aubio_midi_event_t* evt) +{ + return evt->param1; +} + +/* + * aubio_midi_event_set_key + */ +int aubio_midi_event_set_key(aubio_midi_event_t* evt, int v) +{ + evt->param1 = v; + return AUBIO_OK; +} + +/* + * aubio_midi_event_get_velocity + */ +int aubio_midi_event_get_velocity(aubio_midi_event_t* evt) +{ + return evt->param2; +} + +/* + * aubio_midi_event_set_velocity + */ +int aubio_midi_event_set_velocity(aubio_midi_event_t* evt, int v) +{ + evt->param2 = v; + return AUBIO_OK; +} + +/* + * aubio_midi_event_get_control + */ +int aubio_midi_event_get_control(aubio_midi_event_t* evt) +{ + return evt->param1; +} + +/* + * aubio_midi_event_set_control + */ +int aubio_midi_event_set_control(aubio_midi_event_t* evt, int v) +{ + evt->param1 = v; + return AUBIO_OK; +} + +/* + * aubio_midi_event_get_value + */ +int aubio_midi_event_get_value(aubio_midi_event_t* evt) +{ + return evt->param2; +} + +/* + * aubio_midi_event_set_value + */ +int aubio_midi_event_set_value(aubio_midi_event_t* evt, int v) +{ + evt->param2 = v; + return AUBIO_OK; +} + +int aubio_midi_event_get_program(aubio_midi_event_t* evt) +{ + return evt->param1; +} + +int aubio_midi_event_set_program(aubio_midi_event_t* evt, int val) +{ + evt->param1 = val; + return AUBIO_OK; +} + +int aubio_midi_event_get_pitch(aubio_midi_event_t* evt) +{ + return evt->param1; +} + +int aubio_midi_event_set_pitch(aubio_midi_event_t* evt, int val) +{ + evt->param1 = val; + return AUBIO_OK; +} + +/* + * aubio_midi_event_get_param1 + */ +/* int aubio_midi_event_get_param1(aubio_midi_event_t* evt) */ +/* { */ +/* return evt->param1; */ +/* } */ + +/* + * aubio_midi_event_set_param1 + */ +/* int aubio_midi_event_set_param1(aubio_midi_event_t* evt, int v) */ +/* { */ +/* evt->param1 = v; */ +/* return AUBIO_OK; */ +/* } */ + +/* + * aubio_midi_event_get_param2 + */ +/* int aubio_midi_event_get_param2(aubio_midi_event_t* evt) */ +/* { */ +/* return evt->param2; */ +/* } */ + +/* + * aubio_midi_event_set_param2 + */ +/* int aubio_midi_event_set_param2(aubio_midi_event_t* evt, int v) */ +/* { */ +/* evt->param2 = v; */ +/* return AUBIO_OK; */ +/* } */ + diff --git a/ext/midi/midi_event.h b/ext/midi/midi_event.h new file mode 100644 index 00000000..4a9bbe4d --- /dev/null +++ b/ext/midi/midi_event.h @@ -0,0 +1,72 @@ +/* + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA + */ + +/* this file originally taken from FluidSynth - A Software Synthesizer + * Copyright (C) 2003 Peter Hanappe and others. + */ + +/** \file + * midi event structure + */ + +#ifndef _AUBIO_MIDI_EVENT_H +#define _AUBIO_MIDI_EVENT_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _aubio_midi_event_t aubio_midi_event_t; + +/* + * aubio_midi_event_t + */ +struct _aubio_midi_event_t { + aubio_midi_event_t* next; /**< Don't use it, it will dissappear. Used in midi tracks. */ + unsigned int dtime; /**< Delay (ticks) between this and previous event. midi tracks. */ + unsigned char type; /**< MIDI event type */ + unsigned char channel; /**< MIDI channel */ + unsigned int param1; /**< First parameter */ + unsigned int param2; /**< Second parameter */ +}; + +aubio_midi_event_t* new_aubio_midi_event(void); +int del_aubio_midi_event(aubio_midi_event_t* event); +int aubio_midi_event_set_type(aubio_midi_event_t* evt, int type); +int aubio_midi_event_get_type(aubio_midi_event_t* evt); +int aubio_midi_event_set_channel(aubio_midi_event_t* evt, int chan); +int aubio_midi_event_get_channel(aubio_midi_event_t* evt); +int aubio_midi_event_get_key(aubio_midi_event_t* evt); +int aubio_midi_event_set_key(aubio_midi_event_t* evt, int key); +int aubio_midi_event_get_velocity(aubio_midi_event_t* evt); +int aubio_midi_event_set_velocity(aubio_midi_event_t* evt, int vel); +int aubio_midi_event_get_control(aubio_midi_event_t* evt); +int aubio_midi_event_set_control(aubio_midi_event_t* evt, int ctrl); +int aubio_midi_event_get_value(aubio_midi_event_t* evt); +int aubio_midi_event_set_value(aubio_midi_event_t* evt, int val); +int aubio_midi_event_get_program(aubio_midi_event_t* evt); +int aubio_midi_event_set_program(aubio_midi_event_t* evt, int val); +int aubio_midi_event_get_pitch(aubio_midi_event_t* evt); +int aubio_midi_event_set_pitch(aubio_midi_event_t* evt, int val); +int aubio_midi_event_length(unsigned char status); + +#ifdef __cplusplus +} +#endif + +#endif/*_AUBIO_MIDI_EVENT_H*/ diff --git a/ext/midi/midi_file.c b/ext/midi/midi_file.c new file mode 100644 index 00000000..c069a78e --- /dev/null +++ b/ext/midi/midi_file.c @@ -0,0 +1,633 @@ +/* + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA + */ + +/* this file originally taken from FluidSynth - A Software Synthesizer + * Copyright (C) 2003 Peter Hanappe and others. + * + * \note fixed some track names causing segfault + */ + +#include "aubio_priv.h" +#include "midi.h" +#include "midi_event.h" +#include "midi_track.h" +#include "midi_player.h" +#include "midi_file.h" + + +/** aubio_midi_file */ +struct _aubio_midi_file_t{ + //aubio_file_t fp; + FILE *fp; + int running_status; + int c; + int type; + int ntracks; + int uses_smpte; + unsigned int smpte_fps; + unsigned int smpte_res; + unsigned int division; /* If uses_SMPTE == 0 then division is + ticks per beat (quarter-note) */ + double tempo; /* Beats per second (SI rules =) */ + int tracklen; + int trackpos; + int eot; + int varlen; +}; + +/*************************************************************** + * + * MIDIFILE + */ + +/** new_aubio_midi_file */ +aubio_midi_file_t * new_aubio_midi_file(char* filename) +{ + aubio_midi_file_t* mf; + + mf = AUBIO_NEW(aubio_midi_file_t); + if (mf == NULL) { + AUBIO_ERR( "Out of memory"); + return NULL; + } + AUBIO_MEMSET(mf, 0, sizeof(aubio_midi_file_t)); + + mf->c = -1; + mf->running_status = -1; + mf->fp = AUBIO_FOPEN(filename, "rb"); + + if (mf->fp == NULL) { + AUBIO_ERR( "Couldn't open the MIDI file !\n"); + AUBIO_FREE(mf); + return NULL; + } + + if (aubio_midi_file_read_mthd(mf) != AUBIO_OK) { + AUBIO_FREE(mf); + return NULL; + } + return mf; +} + +/** del_aubio_midi_file */ +void del_aubio_midi_file(aubio_midi_file_t* mf) +{ + if (mf == NULL) { + return; + } + if (mf->fp != NULL) { + AUBIO_FCLOSE(mf->fp); + } + AUBIO_FREE(mf); + return; +} + +/** aubio_midi_file_getc */ +int aubio_midi_file_getc(aubio_midi_file_t* mf) +{ + unsigned char c; + int n; + if (mf->c >= 0) { + c = mf->c; + mf->c = -1; + } else { + n = AUBIO_FREAD(&c, 1, 1, mf->fp); + mf->trackpos++; + } + return (int) c; +} + +/** aubio_midi_file_push */ +int aubio_midi_file_push(aubio_midi_file_t* mf, int c) +{ + mf->c = c; + return AUBIO_OK; +} + +/** aubio_midi_file_read */ +int aubio_midi_file_read(aubio_midi_file_t* mf, void* buf, int len) +{ + int num = AUBIO_FREAD(buf, 1, len, mf->fp); + mf->trackpos += num; +#if DEBUG + if (num != len) { + AUBIO_DBG( "Coulnd't read the requested number of bytes"); + } +#endif + return (num != len)? AUBIO_FAIL : AUBIO_OK; +} + +/** aubio_midi_file_skip */ +int aubio_midi_file_skip(aubio_midi_file_t* mf, int skip) +{ + int err = AUBIO_FSEEK(mf->fp, skip, SEEK_CUR); + if (err) { + AUBIO_ERR( "FAIL to seek position in file"); + return AUBIO_FAIL; + } + return AUBIO_OK; +} + +/** aubio_midi_file_read_mthd */ +int aubio_midi_file_read_mthd(aubio_midi_file_t* mf) +{ + char mthd[15]; + if (aubio_midi_file_read(mf, mthd, 14) != AUBIO_OK) { + return AUBIO_FAIL; + } + if ((AUBIO_STRNCMP(mthd, "MThd", 4) != 0) || (mthd[7] != 6) || (mthd[9] > 2)) { + AUBIO_ERR( "Doesn't look like a MIDI file: invalid MThd header"); + return AUBIO_FAIL; + } + mf->type = mthd[9]; + mf->ntracks = (unsigned) mthd[11]; + mf->ntracks += (unsigned int) (mthd[10]) << 16; + /** \bug: smpte timing not yet implemented */ + if((int)(mthd[12]) < 0){ + /*if((mthd[12]) < 0){*/ + mf->uses_smpte = 1; + mf->smpte_fps = -mthd[12]; + mf->smpte_res = (unsigned) mthd[13]; + AUBIO_ERR( "File uses SMPTE timing -- Not implemented yet"); + return AUBIO_FAIL; + } else { + mf->uses_smpte = 0; + mf->division = (mthd[12] << 8) | (mthd[13] & 0xff); + } + return AUBIO_OK; +} + +/** aubio_midi_file_load_tracks */ +int aubio_midi_file_load_tracks(aubio_midi_file_t* mf, aubio_midi_player_t* player) +{ + int i; + for (i = 0; i < mf->ntracks; i++) { + if (aubio_midi_file_read_track(mf, player, i) != AUBIO_OK) { + return AUBIO_FAIL; + } + } + return AUBIO_OK; +} + +/** aubio_midi_file_read_tracklen */ +int aubio_midi_file_read_tracklen(aubio_midi_file_t* mf) +{ + unsigned char length[5]; + if (aubio_midi_file_read(mf, length, 4) != AUBIO_OK) { + return AUBIO_FAIL; + } + mf->tracklen = aubio_getlength(length); + mf->trackpos = 0; + mf->eot = 0; + return AUBIO_OK; +} + +/** aubio_midi_file_eot */ +int aubio_midi_file_eot(aubio_midi_file_t* mf) +{ +#if DEBUG + if (mf->trackpos > mf->tracklen) { + printf("track overrun: %d > %d\n", mf->trackpos, mf->tracklen); + } +#endif + return mf->eot || (mf->trackpos >= mf->tracklen); +} + +/** aubio_midi_file_read_track */ +int aubio_midi_file_read_track(aubio_midi_file_t* mf, aubio_midi_player_t* player, int num) +{ + aubio_track_t* track; + unsigned char id[5], length[5]; + int found_track = 0; + int skip; + + AUBIO_DBG("Loading track %d\n",num); + if (aubio_midi_file_read(mf, id, 4) != AUBIO_OK) { + AUBIO_DBG("Failed loading track %d\n",num); + return AUBIO_FAIL; + } + + id[4]='\0'; + + while (!found_track){ + + if (aubio_isasciistring((char*) id) == 0) { + AUBIO_ERR( "An non-ascii track header found, currupt file"); + return AUBIO_FAIL; + + } else if (strcmp((char*) id, "MTrk") == 0) { + + found_track = 1; + + if (aubio_midi_file_read_tracklen(mf) != AUBIO_OK) { + return AUBIO_FAIL; + } + + track = new_aubio_track(num); + if (track == NULL) { + AUBIO_ERR( "Out of memory"); + return AUBIO_FAIL; + } + + while (!aubio_midi_file_eot(mf)) { + if (aubio_midi_file_read_event(mf, track) != AUBIO_OK) { + return AUBIO_FAIL; + } + } + + aubio_midi_player_add_track(player, track); + } else { + found_track = 0; + if (aubio_midi_file_read(mf, length, 4) != AUBIO_OK) { + return AUBIO_FAIL; + } + skip = aubio_getlength(length); + /* fseek(mf->fp, skip, SEEK_CUR); */ + if (aubio_midi_file_skip(mf, skip) != AUBIO_OK) { + return AUBIO_FAIL; + } + } + } + + if (feof(mf->fp)) { + AUBIO_ERR( "Unexpected end of file"); + return AUBIO_FAIL; + } + AUBIO_DBG("Loaded track %d\n",num); + return AUBIO_OK; +} + +/** aubio_midi_file_read_varlen */ +int aubio_midi_file_read_varlen(aubio_midi_file_t* mf) +{ + int i; + int c; + mf->varlen = 0; + for (i = 0;;i++) { + if (i == 4) { + AUBIO_ERR( "Invalid variable length number"); + return AUBIO_FAIL; + } + c = aubio_midi_file_getc(mf); + if (c < 0) { + AUBIO_ERR( "Unexpected end of file"); + return AUBIO_FAIL; + } + if (c & 0x80){ + mf->varlen |= (int) (c & 0x7F); + mf->varlen <<= 7; + } else { + mf->varlen += c; + break; + } + } + return AUBIO_OK; +} + +/** aubio_midi_file_read_event */ +int aubio_midi_file_read_event(aubio_midi_file_t* mf, aubio_track_t* track) +{ + int dtime; + int status; + int type; + int tempo; + unsigned char* metadata = NULL; + unsigned char* dyn_buf = NULL; + unsigned char static_buf[256]; + int nominator, denominator, clocks, notes, sf, mi; + aubio_midi_event_t* evt; + int channel = 0; + int param1 = 0; + int param2 = 0; + + + /* read the delta-time of the event */ + if (aubio_midi_file_read_varlen(mf) != AUBIO_OK) { + return AUBIO_FAIL; + } + dtime = mf->varlen; + + /* read the status byte */ + status = aubio_midi_file_getc(mf); + if (status < 0) { + AUBIO_ERR( "Unexpected end of file"); + return AUBIO_FAIL; + } + + /* not a valid status byte: use the running status instead */ + if ((status & 0x80) == 0) { + if ((mf->running_status & 0x80) == 0) { + AUBIO_ERR( "Undefined status and invalid running status"); + return AUBIO_FAIL; + } + aubio_midi_file_push(mf, status); + status = mf->running_status; + } + + /* check what message we have */ + if (status & 0x80) { + mf->running_status = status; + + if ((status == MIDI_SYSEX) || (status == MIDI_EOX)) { /* system exclusif */ + /** \bug Sysex messages are not handled yet */ + /* read the length of the message */ + if (aubio_midi_file_read_varlen(mf) != AUBIO_OK) { + return AUBIO_FAIL; + } + + if (mf->varlen < 255) { + metadata = &static_buf[0]; + } else { + AUBIO_DBG( "%s: %d: alloc metadata, len = %d", __FILE__, __LINE__, mf->varlen); + dyn_buf = AUBIO_MALLOC(mf->varlen + 1); + if (dyn_buf == NULL) { + //AUBIO_LOG(AUBIO_PANIC, "Out of memory"); + AUBIO_ERR("Out of memory"); + return AUBIO_FAIL; + } + metadata = dyn_buf; + } + + /* read the data of the message */ + if (mf->varlen) { + + if (aubio_midi_file_read(mf, metadata, mf->varlen) != AUBIO_OK) { + if (dyn_buf) { + AUBIO_FREE(dyn_buf); + } + return AUBIO_FAIL; + } + + if (dyn_buf) { + AUBIO_DBG( "%s: %d: free metadata", __FILE__, __LINE__); + AUBIO_FREE(dyn_buf); + } + } + + return AUBIO_OK; + + } else if (status == MIDI_META_EVENT) { /* meta events */ + + int result = AUBIO_OK; + + /* get the type of the meta message */ + type = aubio_midi_file_getc(mf); + if (type < 0) { + AUBIO_ERR( "Unexpected end of file"); + return AUBIO_FAIL; + } + + /* get the length of the data part */ + if (aubio_midi_file_read_varlen(mf) != AUBIO_OK) { + return AUBIO_FAIL; + } + + if (mf->varlen) { + + if (mf->varlen < 255) { + metadata = &static_buf[0]; + } else { + AUBIO_DBG( "%s: %d: alloc metadata, len = %d", __FILE__, __LINE__, mf->varlen); + dyn_buf = AUBIO_MALLOC(mf->varlen + 1); + if (dyn_buf == NULL) { + AUBIO_ERR("Out of memory"); + return AUBIO_FAIL; + } + metadata = dyn_buf; + } + + /* read the data */ + if (aubio_midi_file_read(mf, metadata, mf->varlen) != AUBIO_OK) { + if (dyn_buf) { + AUBIO_FREE(dyn_buf); + } + return AUBIO_FAIL; + } + } + + /* handle meta data */ + switch (type) { + + case MIDI_COPYRIGHT: + metadata[mf->varlen] = 0; + break; + + case MIDI_TRACK_NAME: + if (metadata != NULL) /* avoids crashes on empty tracks */ + metadata[mf->varlen] = 0; + aubio_track_set_name(track, (char*) metadata); + break; + + case MIDI_INST_NAME: + metadata[mf->varlen] = 0; + break; + + case MIDI_LYRIC: + break; + + case MIDI_MARKER: + break; + + case MIDI_CUE_POINT: + break; /* don't care much for text events */ + + case MIDI_EOT: + if (mf->varlen != 0) { + AUBIO_ERR("Invalid length for EndOfTrack event"); + result = AUBIO_FAIL; + break; + } + mf->eot = 1; + break; + + case MIDI_SET_TEMPO: + if (mf->varlen != 3) { + AUBIO_ERR("Invalid length for SetTempo meta event"); + result = AUBIO_FAIL; + break; + } + tempo = (metadata[0] << 16) + (metadata[1] << 8) + metadata[2]; + evt = new_aubio_midi_event(); + if (evt == NULL) { + AUBIO_ERR( "Out of memory"); + result = AUBIO_FAIL; + break; + } + evt->dtime = dtime; + evt->type = MIDI_SET_TEMPO; + evt->channel = 0; + evt->param1 = tempo; + evt->param2 = 0; + aubio_track_add_event(track, evt); + break; + + case MIDI_SMPTE_OFFSET: + if (mf->varlen != 5) { + AUBIO_ERR("Invalid length for SMPTE Offset meta event"); + result = AUBIO_FAIL; + break; + } + break; /* we don't use smtp */ + + case MIDI_TIME_SIGNATURE: + if (mf->varlen != 4) { + AUBIO_ERR("Invalid length for TimeSignature meta event"); + result = AUBIO_FAIL; + break; + } + nominator = metadata[0]; + denominator = pow(2.0, (double) metadata[1]); + clocks = metadata[2]; + notes = metadata[3]; + + AUBIO_DBG("signature=%d/%d, metronome=%d, 32nd-notes=%d\n", + nominator, denominator, clocks, notes); + + break; + + case MIDI_KEY_SIGNATURE: + if (mf->varlen != 2) { + AUBIO_ERR( "Invalid length for KeySignature meta event"); + result = AUBIO_FAIL; + break; + } + sf = metadata[0]; + mi = metadata[1]; + break; + + case MIDI_SEQUENCER_EVENT: + AUBIO_DBG("Sequencer event ignored\n"); + break; + + default: + break; + } + + if (dyn_buf) { + AUBIO_DBG( "%s: %d: free metadata", __FILE__, __LINE__); + AUBIO_FREE(dyn_buf); + } + + return result; + + } else { /* channel messages */ + + type = status & 0xf0; + channel = status & 0x0f; + + /* all channel message have at least 1 byte of associated data */ + if ((param1 = aubio_midi_file_getc(mf)) < 0) { + AUBIO_ERR( "Unexpected end of file"); + return AUBIO_FAIL; + } + + switch (type) { + + case NOTE_ON: + if ((param2 = aubio_midi_file_getc(mf)) < 0) { + AUBIO_ERR( "Unexpected end of file"); + return AUBIO_FAIL; + } + break; + + case NOTE_OFF: + if ((param2 = aubio_midi_file_getc(mf)) < 0) { + AUBIO_ERR( "Unexpected end of file"); + return AUBIO_FAIL; + } + break; + + case KEY_PRESSURE: + if ((param2 = aubio_midi_file_getc(mf)) < 0) { + AUBIO_ERR( "Unexpected end of file"); + return AUBIO_FAIL; + } + break; + + case CONTROL_CHANGE: + if ((param2 = aubio_midi_file_getc(mf)) < 0) { + AUBIO_ERR( "Unexpected end of file"); + return AUBIO_FAIL; + } + break; + + case PROGRAM_CHANGE: + break; + + case CHANNEL_PRESSURE: + break; + + case PITCH_BEND: + if ((param2 = aubio_midi_file_getc(mf)) < 0) { + AUBIO_ERR( "Unexpected end of file"); + return AUBIO_FAIL; + } + + param1 = ((param2 & 0x7f) << 7) | (param1 & 0x7f); + param2 = 0; + break; + + default: + /* Can't possibly happen !? */ + AUBIO_ERR( "Unrecognized MIDI event"); + return AUBIO_FAIL; + } + evt = new_aubio_midi_event(); + if (evt == NULL) { + AUBIO_ERR( "Out of memory"); + return AUBIO_FAIL; + } + evt->dtime = dtime; + evt->type = type; + evt->channel = channel; + evt->param1 = param1; + evt->param2 = param2; + aubio_track_add_event(track, evt); + } + } + return AUBIO_OK; +} + +/** aubio_midi_file_get_division */ +int aubio_midi_file_get_division(aubio_midi_file_t* midifile) +{ + return midifile->division; +} + + +/** aubio_isasciistring */ +int aubio_isasciistring(char* s) +{ + int i; + int len = (int) AUBIO_STRLEN(s); + for (i = 0; i < len; i++) { + if (!aubio_isascii(s[i])) { + return 0; + } + } + return 1; +} + +/** aubio_getlength */ +long aubio_getlength(unsigned char *s) +{ + long i = 0; + i = s[3] | (s[2]<<8) | (s[1]<<16) | (s[0]<<24); + return i; +} + diff --git a/ext/midi/midi_file.h b/ext/midi/midi_file.h new file mode 100644 index 00000000..9c9fb0da --- /dev/null +++ b/ext/midi/midi_file.h @@ -0,0 +1,62 @@ +/* + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA + */ + +/* this file originally taken from FluidSynth - A Software Synthesizer + * Copyright (C) 2003 Peter Hanappe and others. + */ + +/** \file + * midi file reader + */ + +#ifndef _AUBIO_MIDI_FILE_H +#define _AUBIO_MIDI_FILE_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _aubio_midi_file_t aubio_midi_file_t; + + +aubio_midi_file_t* new_aubio_midi_file(char* filename); +void del_aubio_midi_file(aubio_midi_file_t* mf); +int aubio_midi_file_read_mthd(aubio_midi_file_t* midifile); +int aubio_midi_file_load_tracks(aubio_midi_file_t* midifile, aubio_midi_player_t* player); +int aubio_midi_file_read_track(aubio_midi_file_t* mf, aubio_midi_player_t* player, int num); +int aubio_midi_file_read_event(aubio_midi_file_t* mf, aubio_track_t* track); +int aubio_midi_file_read_varlen(aubio_midi_file_t* mf); +int aubio_midi_file_getc(aubio_midi_file_t* mf); +int aubio_midi_file_push(aubio_midi_file_t* mf, int c); +int aubio_midi_file_read(aubio_midi_file_t* mf, void* buf, int len); +int aubio_midi_file_skip(aubio_midi_file_t* mf, int len); +int aubio_midi_file_read_tracklen(aubio_midi_file_t* mf); +int aubio_midi_file_eot(aubio_midi_file_t* mf); +int aubio_midi_file_get_division(aubio_midi_file_t* midifile); + + +/* From ctype.h */ +#define aubio_isascii(c) (((c) & ~0x7f) == 0) +int aubio_isasciistring(char* s); +long aubio_getlength(unsigned char *s); + +#ifdef __cplusplus +} +#endif + +#endif /*_AUBIO_MIDI_FILE_H*/ diff --git a/ext/midi/midi_parser.c b/ext/midi/midi_parser.c new file mode 100644 index 00000000..ed47935a --- /dev/null +++ b/ext/midi/midi_parser.c @@ -0,0 +1,221 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA + */ + +/* This file orginally taken from, Fluidsynth, Peter Hanappe */ + +#include "aubio_priv.h" +#include "midi.h" +#include "midi_event.h" +#include "midi_parser.h" + +/** aubio_midi_parser_t */ +struct _aubio_midi_parser_t { + unsigned char status; /**< Identifies the type of event, that is + currently received ('Noteon', 'Pitch Bend' + etc). */ + unsigned char channel; /**< The channel of the event that is received + (in case of a channel event) */ + unsigned int nr_bytes; /**< How many bytes have been read for the + current event? */ + unsigned int nr_bytes_total;/**< How many bytes does the current event + type include? */ + unsigned short p[AUBIO_MIDI_PARSER_MAX_PAR]; /**< The parameters */ + + aubio_midi_event_t event; /**< The event, that is returned to the + MIDI driver. */ +}; + +/** new_aubio_midi_parser */ +aubio_midi_parser_t* new_aubio_midi_parser() +{ + aubio_midi_parser_t* parser; + parser = AUBIO_NEW(aubio_midi_parser_t); + if (parser == NULL) { + AUBIO_ERR("Out of memory"); + return NULL; + } + /* As long as the status is 0, the parser won't do anything -> no need to + * initialize all the fields. */ + parser->status = 0; + return parser; +} + +/** del_aubio_midi_parser */ +int del_aubio_midi_parser(aubio_midi_parser_t* parser) +{ + AUBIO_FREE(parser); + return AUBIO_OK; +} + +/** aubio_midi_parser_parse + * + * The MIDI byte stream is fed into the parser, one byte at a time. + * As soon as the parser has recognized an event, it will return it. + * Otherwise it returns NULL. + */ +aubio_midi_event_t* aubio_midi_parser_parse(aubio_midi_parser_t* parser, + unsigned char c) +{ + /*********************************************************************/ + /* 'Process' system real-time messages */ + /*********************************************************************/ + /* There are not too many real-time messages that are of interest here. + * They can occur anywhere, even in the middle of a noteon message! + * Real-time range: 0xF8 .. 0xFF + * Note: Real-time does not affect (running) status. + */ + if (c >= 0xF8){ + if (c == MIDI_SYSTEM_RESET){ + parser->event.type = c; + parser->status = 0; /* clear the status */ + return &parser->event; + }; + return NULL; + }; + + /*********************************************************************/ + /* 'Process' system common messages (again, just skip them) */ + /*********************************************************************/ + /* There are no system common messages that are of interest here. + * System common range: 0xF0 .. 0xF7 + */ + + if (c > 0xF0){ + /* MIDI specs say: To ignore a non-real-time message, just discard all data + * up to the next status byte. And our parser will ignore data that is + * received without a valid status. + * Note: system common cancels running status. */ + parser->status = 0; + return NULL; + }; + + /*********************************************************************/ + /* Process voice category messages: */ + /*********************************************************************/ + /* Now that we have handled realtime and system common messages, only + * voice messages are left. + * Only a status byte has bit # 7 set. + * So no matter the status of the parser (in case we have lost sync), + * as soon as a byte >= 0x80 comes in, we are dealing with a status byte + * and start a new event. + */ + + if (c & 0x80){ + parser->channel = c & 0x0F; + parser->status = c & 0xF0; + /* The event consumes x bytes of data... (subtract 1 for the status + * byte) */ + parser->nr_bytes_total=aubio_midi_event_length(parser->status)-1; + /* of which we have read 0 at this time. */ + parser->nr_bytes = 0; + return NULL; + }; + + /*********************************************************************/ + /* Process data */ + /*********************************************************************/ + /* If we made it this far, then the received char belongs to the data + * of the last event. */ + if (parser->status == 0){ + /* We are not interested in the event currently received. + * Discard the data. */ + return NULL; + }; + + /* Store the first couple of bytes */ + if (parser->nr_bytes < AUBIO_MIDI_PARSER_MAX_PAR){ + parser->p[parser->nr_bytes]=c; + }; + parser->nr_bytes++; + + /* Do we still need more data to get this event complete? */ + if (parser->nr_bytes < parser->nr_bytes_total){ + return NULL; + }; + + /*********************************************************************/ + /* Send the event */ + /*********************************************************************/ + /* The event is ready-to-go. About 'running status': + * + * The MIDI protocol has a built-in compression mechanism. If several similar + * events are sent in-a-row, for example note-ons, then the event type is + * only sent once. For this case, the last event type (status) is remembered. + * We simply keep the status as it is, just reset the parameter counter. If + * another status byte comes in, it will overwrite the status. + */ + parser->event.type = parser->status; + parser->event.channel = parser->channel; + parser->nr_bytes = 0; /* Related to running status! */ + switch (parser->status){ + case NOTE_OFF: + case NOTE_ON: + case KEY_PRESSURE: + case CONTROL_CHANGE: + case PROGRAM_CHANGE: + case CHANNEL_PRESSURE: + parser->event.param1 = parser->p[0]; /* For example key number */ + parser->event.param2 = parser->p[1]; /* For example velocity */ + break; + case PITCH_BEND: + /* Pitch-bend is transmitted with 14-bit precision. */ + /* Note: '|' does here the same as '+' (no common bits), + * but might be faster */ + parser->event.param1 = ((parser->p[1] << 7) | parser->p[0]); + break; + default: + /* Unlikely */ + return NULL; + }; + return &parser->event; +}; + + + +/* Taken from Nagano Daisuke's USB-MIDI driver */ +static int remains_f0f6[] = { + 0, /* 0xF0 */ + 2, /* 0XF1 */ + 3, /* 0XF2 */ + 2, /* 0XF3 */ + 2, /* 0XF4 (Undefined by MIDI Spec, and subject to change) */ + 2, /* 0XF5 (Undefined by MIDI Spec, and subject to change) */ + 1 /* 0XF6 */ +}; + +static int remains_80e0[] = { + 3, /* 0x8X Note Off */ + 3, /* 0x9X Note On */ + 3, /* 0xAX Poly-key pressure */ + 3, /* 0xBX Control Change */ + 2, /* 0xCX Program Change */ + 2, /* 0xDX Channel pressure */ + 3 /* 0xEX PitchBend Change */ +}; + +/** Returns the length of the MIDI message starting with c. + * + * Taken from Nagano Daisuke's USB-MIDI driver */ +int aubio_midi_event_length(unsigned char event){ + if ( event < 0xf0 ) { + return remains_80e0[((event-0x80)>>4)&0x0f]; + } else if ( event < 0xf7 ) { + return remains_f0f6[event-0xf0]; + } else { + return 1; + } +} diff --git a/ext/midi/midi_parser.h b/ext/midi/midi_parser.h new file mode 100644 index 00000000..6fa25df1 --- /dev/null +++ b/ext/midi/midi_parser.h @@ -0,0 +1,49 @@ +/* + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA + */ + +/* this file originally taken from FluidSynth - A Software Synthesizer + * Copyright (C) 2003 Peter Hanappe and others. + */ + + +/** \file + * midi parser + */ + +#ifndef _AUBIO_MIDI_PARSER_H +#define _AUBIO_MIDI_PARSER_H + + +#ifdef __cplusplus +extern "C" { +#endif + +/* How many parameters may a MIDI event have? */ +#define AUBIO_MIDI_PARSER_MAX_PAR 3 + +typedef struct _aubio_midi_parser_t aubio_midi_parser_t; + +aubio_midi_parser_t* new_aubio_midi_parser(void); +int del_aubio_midi_parser(aubio_midi_parser_t* parser); +aubio_midi_event_t* aubio_midi_parser_parse(aubio_midi_parser_t* parser, unsigned char c); + +#ifdef __cplusplus +} +#endif + +#endif /*_AUBIO_MIDI_PARSER_H*/ diff --git a/ext/midi/midi_player.c b/ext/midi/midi_player.c new file mode 100644 index 00000000..94854429 --- /dev/null +++ b/ext/midi/midi_player.c @@ -0,0 +1,492 @@ +/* + * Copyright (C) 2003 Peter Hanappe and others. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA + */ + +/* this file originally taken from FluidSynth - A Software Synthesizer + * modified by Paul Brossier for aubio + */ + +/** + * + * \bug timer still broken + * (should use alsa seq anyway) (fixed?) realtime playing is slower than + * it should. moved msec_passed and deltatime to microseconds (usec) + * (rounding were causing the drift) the new offline version is not quite + * exact yet. + * + * \bug the player does not seem to understand a ``reprise'' in a file + */ + +#include "aubio_priv.h" +#include "list.h" +#include "timer.h" +#include "midi.h" +#include "midi_event.h" +#include "midi_track.h" +#include "midi_player.h" +#include "midi_file.h" + + +/** aubio_midi_player */ +struct _aubio_midi_player_t { + aubio_track_t *track[AUBIO_MIDI_PLAYER_MAX_TRACKS]; + aubio_timer_t* timer; + sint_t status; + sint_t loop; + sint_t ntracks; + aubio_list_t* playlist; + char* current_file; + char send_program_change;/**< should we ignore the program changes? */ + sint_t ticks_passed; /**< number of midi ticks that have passed */ + sint_t usec_passed; /**< number of microseconds that have passed */ + sint_t miditempo; /**< as indicated by midi settempo: n 24th of a + * usec per midi-clock. bravo! */ + lsmp_t deltatime; /**< microseconds per midi tick. depends on + * set-tempo */ + uint_t division; /**< the number of ticks per beat (quarter-note) + * in the file*/ + //aubio_synth_t* synth; +}; + +/****************************************************** + * + * aubio_midi_player + */ +/** new_aubio_midi_player */ +aubio_midi_player_t* new_aubio_midi_player() + //aubio_midi_player_t* new_aubio_midi_player(aubio_synth_t* synth) +{ + sint_t i; + aubio_midi_player_t* player; + player = AUBIO_NEW(aubio_midi_player_t); + if (player == NULL) { + AUBIO_ERR( "Out of memory"); + return NULL; + } + player->status = AUBIO_MIDI_PLAYER_READY; + player->loop = 0; + player->ntracks = 0; + for (i = 0; i < AUBIO_MIDI_PLAYER_MAX_TRACKS; i++) { + player->track[i] = NULL; + } + //player->synth = synth; + player->timer = NULL; + player->playlist = NULL; + player->current_file = NULL; + player->division = 0; + player->send_program_change = 1; + player->ticks_passed = 0; + player->usec_passed = 0; + player->miditempo = 480000; + player->deltatime = 4000.0; + return player; +} + +/** delete_aubio_midi_player */ +sint_t del_aubio_midi_player(aubio_midi_player_t* player) +{ + if (player == NULL) { + return AUBIO_OK; + } + aubio_midi_player_stop(player); + aubio_midi_player_reset(player); + AUBIO_FREE(player); + return AUBIO_OK; +} + +/** aubio_midi_player_reset */ +sint_t aubio_midi_player_reset(aubio_midi_player_t* player) +{ + sint_t i; + + for (i = 0; i < AUBIO_MIDI_PLAYER_MAX_TRACKS; i++) { + if (player->track[i] != NULL) { + del_aubio_track(player->track[i]); + player->track[i] = NULL; + } + } + player->current_file = NULL; + player->status = AUBIO_MIDI_PLAYER_READY; + player->loop = 0; + player->ntracks = 0; + player->division = 0; + player->send_program_change = 1; + player->ticks_passed = 0; + player->usec_passed = 0; + player->miditempo = 480000; + player->deltatime = 4000.0; + return 0; +} + +/** aubio_midi_player_add_track */ +sint_t aubio_midi_player_add_track(aubio_midi_player_t* player, aubio_track_t* track) +{ + if (player->ntracks < AUBIO_MIDI_PLAYER_MAX_TRACKS) { + player->track[player->ntracks++] = track; + return AUBIO_OK; + } else { + return AUBIO_FAIL; + } +} + +/** aubio_midi_player_count_tracks */ +sint_t aubio_midi_player_count_tracks(aubio_midi_player_t* player) +{ + return player->ntracks; +} + +/** aubio_midi_player_get_track */ +aubio_track_t* aubio_midi_player_get_track(aubio_midi_player_t* player, sint_t i) +{ + if ((i >= 0) && (i < AUBIO_MIDI_PLAYER_MAX_TRACKS)) { + return player->track[i]; + } else { + return NULL; + } +} + +/** aubio_midi_player_get_track */ +sint_t aubio_midi_player_add(aubio_midi_player_t* player, char* midifile) +{ + char *s = AUBIO_STRDUP(midifile); + player->playlist = aubio_list_append(player->playlist, s); + return 0; +} + +/** aubio_midi_player_load */ +sint_t aubio_midi_player_load(aubio_midi_player_t* player, char *filename) +{ + aubio_midi_file_t* midifile; + + midifile = new_aubio_midi_file(filename); + if (midifile == NULL) { + return AUBIO_FAIL; + } + player->division = aubio_midi_file_get_division(midifile); + + AUBIO_DBG("quarter note division=%d\n", player->division); + + if (aubio_midi_file_load_tracks(midifile, player) != AUBIO_OK){ + return AUBIO_FAIL; + } + + AUBIO_DBG("Tracks loaded\n"); + + del_aubio_midi_file(midifile); + return AUBIO_OK; +} + +/** aubio_midi_player_callback */ +sint_t aubio_midi_player_callback(void* data, uint_t usec) +{ + sint_t i; + uint_t ticks; + uint_t delta_ticks; + sint_t status = AUBIO_MIDI_PLAYER_DONE; + aubio_midi_player_t* player; + //aubio_synth_t* synth; + player = (aubio_midi_player_t*) data; + //synth = player->synth; + + /* Load the next file if necessary */ + while (player->current_file == NULL) { + + if (player->playlist == NULL) { + return 0; + } + + aubio_midi_player_reset(player); + + player->current_file = aubio_list_get(player->playlist); + player->playlist = aubio_list_next(player->playlist); + + //AUBIO_DBG( "%s: %d: Loading midifile %s", __FILE__, __LINE__, player->current_file); + AUBIO_DBG("Loading midifile %s\n", player->current_file); + + if (aubio_midi_player_load(player, player->current_file) == AUBIO_OK) { + + player->ticks_passed = 0; + player->usec_passed = 0; + + for (i = 0; i < player->ntracks; i++) { + if (player->track[i] != NULL) { + aubio_track_reset(player->track[i]); + } + } + + } else { + player->current_file = NULL; + } + } + + delta_ticks = (uint_t) ((lsmp_t)(usec - player->usec_passed) / player->deltatime); + ticks = player->ticks_passed + delta_ticks; + + for (i = 0; i < player->ntracks; i++) { + if (!aubio_track_eot(player->track[i])) { + status = AUBIO_MIDI_PLAYER_PLAYING; + if (aubio_track_send_events(player->track[i], /*synth,*/ player, ticks) != AUBIO_OK) { + /* */ + } + } + } + + player->status = status; + player->ticks_passed = ticks; + player->usec_passed = usec; + + if (player->status == AUBIO_MIDI_PLAYER_DONE) { + player->current_file = NULL; + } + + return 1; +} + +/** aubio_midi_player_play */ +sint_t aubio_midi_player_play(aubio_midi_player_t* player) +{ + AUBIO_DBG("Starting midi player\n"); + if (player->status == AUBIO_MIDI_PLAYER_PLAYING) { + AUBIO_DBG("Midi player already playing\n"); + return AUBIO_OK; + } + + if (player->playlist == NULL) { + AUBIO_DBG("No playlist\n"); + return AUBIO_FAIL; + } + + player->status = AUBIO_MIDI_PLAYER_PLAYING; + + /** \bug timer is still in millisec, should be moved to microseconds, + * and replaced in favor of the alsa sequencer api */ + player->timer = new_aubio_timer((sint_t) player->deltatime * 1.e-3, aubio_midi_player_callback, + (void*) player, 1, 0); + if (player->timer == NULL) { + AUBIO_DBG("Failed creating timer for midi player.\n"); + return AUBIO_FAIL; + } + if (player->current_file == NULL) { + AUBIO_DBG("No more file.\n"); + delete_aubio_timer(player->timer); + return AUBIO_FAIL; + } + + return AUBIO_OK; +} + +/** aubio_midi_player_play_offline */ +sint_t aubio_midi_player_play_offline(aubio_midi_player_t* player) +{ + uint_t usec = 0; /* start looking n ms in advance */ + AUBIO_DBG("Starting midi player\n"); + if (player->status == AUBIO_MIDI_PLAYER_PLAYING) { + AUBIO_DBG("Midi player already playing\n"); + return AUBIO_OK; + } + + if (player->playlist == NULL) { + AUBIO_DBG("No playlist\n"); + return AUBIO_FAIL; + } + + //AUBIO_DBG("Starting callback.\n"); + player->status = AUBIO_MIDI_PLAYER_PLAYING; + + /* no timer, no thread ! */ + while(aubio_midi_player_callback((void *)player,usec)) + { + /* step at least one microsecond forward */ + usec += 1 + player->deltatime; + if (player->status == AUBIO_MIDI_PLAYER_DONE) + break; + } + //AUBIO_DBG("End of callback.\n"); + + if (player->current_file == NULL) { + AUBIO_DBG("No more file.\n"); + return AUBIO_FAIL; + } + return AUBIO_OK; +} +/** aubio_midi_player_stop */ +sint_t aubio_midi_player_stop(aubio_midi_player_t* player) +{ + if (player->timer != NULL) { + delete_aubio_timer(player->timer); + } + player->status = AUBIO_MIDI_PLAYER_DONE; + player->timer = NULL; + return AUBIO_OK; +} + +/** aubio_midi_player_set_loop */ +sint_t aubio_midi_player_set_loop(aubio_midi_player_t* player, sint_t loop) +{ + player->loop = loop; + return AUBIO_OK; +} + +/** aubio_midi_player_set_midi_tempo */ +sint_t aubio_midi_player_set_midi_tempo(aubio_midi_player_t* player, sint_t tempo) +{ + player->miditempo = tempo; + //player->deltatime = (lsmp_t) tempo / player->division * 1.e-3; /* in milliseconds */ + player->deltatime = (lsmp_t) tempo / player->division; /* in microseconds */ + + AUBIO_DBG("Tempo Change: %d tempo=%f tick time=%f msec\n", + // player->usec_passed, 60.*1.e6/tempo, player->deltatime); + player->usec_passed, 60.*1.e6/tempo, 1e-3*player->deltatime); + + return AUBIO_OK; +} + +/** aubio_midi_player_set_bpm */ +sint_t aubio_midi_player_set_bpm(aubio_midi_player_t* player, sint_t bpm) +{ + return aubio_midi_player_set_midi_tempo(player, (sint_t)((lsmp_t) 60 * 1e6 / bpm)); +} + +/** aubio_midi_player_join */ +sint_t aubio_midi_player_join(aubio_midi_player_t* player) +{ + return player->timer? aubio_timer_join(player->timer) : AUBIO_OK; +} + +/** aubio_track_send_events */ +sint_t aubio_track_send_events(aubio_track_t* track, + // aubio_synth_t* synth, + aubio_midi_player_t* player, + uint_t ticks) +{ + sint_t status = AUBIO_OK; + aubio_midi_event_t* event; + + while (1) { + + event = track->cur; + if (event == NULL) { + return status; + } + /* prsint_t each midi tick */ + /* + AUBIO_DBG("track=%d\tticks=%u\ttrack=%u\tdtime=%u\tnext=%u\n", + track->num, + ticks, + track->ticks, + event->dtime, + track->ticks + event->dtime); + */ + + if (track->ticks + event->dtime > ticks) { + return status; + } + + track->ticks += event->dtime; + status = aubio_midi_send_event(/*synth, */player, event); + aubio_track_next_event(track); + + } + return status; +} + + +/** + * aubio_midi_send_event + * + * This is a utility function that doesn't really belong to any class or + * structure. It is called by aubio_midi_track and aubio_midi_device. + * + * \note This could be moved to a callback function defined in the main programs + */ +//sint_t aubio_midi_send_event(aubio_synth_t* synth, aubio_player_t* player, aubio_midi_event_t* event) +sint_t aubio_midi_send_event(aubio_midi_player_t* player, aubio_midi_event_t* event) +{ + /* current time in seconds */ + //smpl_t print_time = player->msec_passed * 1e-3; + smpl_t print_time = player->usec_passed * 1e-6; + switch (event->type) { + case NOTE_ON: + AUBIO_MSG("Time=%f, chan=%d, pitch=%d vol=%d \n", + print_time, event->channel, event->param1, event->param2); + /*if (aubio_synth_noteon(synth, event->channel, event->param1, event->param2) != AUBIO_OK) { + return AUBIO_FAIL; + }*/ + break; + case NOTE_OFF: + AUBIO_MSG("Time=%f, chan=%d, pitch=%d, vol=0\n", + print_time, event->channel, event->param1); + /*if (aubio_synth_noteoff(synth, event->channel, event->param1) != AUBIO_OK) { + return AUBIO_FAIL; + }*/ + break; + case CONTROL_CHANGE: + AUBIO_MSG("Time=%f Parameter, chan=%d c1=%d c2=%d\n", + print_time, event->channel, event->param1, event->param2); + /*if (aubio_synth_cc(synth, event->channel, event->param1, event->param2) != AUBIO_OK) { + return AUBIO_FAIL; + }*/ + break; + case MIDI_SET_TEMPO: + if (player != NULL) { + if (aubio_midi_player_set_midi_tempo(player, event->param1) != AUBIO_OK) { + return AUBIO_FAIL; + } + } + break; + case PROGRAM_CHANGE: + AUBIO_MSG("Time=%f Program, chan=%d program=%d\n", + print_time, event->channel, event->param1); + /*if (aubio_synth_program_change(synth, event->channel, event->param1) != AUBIO_OK) { + return AUBIO_FAIL; + }*/ + break; + case PITCH_BEND: + AUBIO_MSG("Time=%f Pitchbend, chan=%d msb=%d lsb=%d \n", + print_time, event->channel, event->param1, event->param2); + /*if (aubio_synth_pitch_bend(synth, event->channel, event->param1) != AUBIO_OK) { + return AUBIO_FAIL; + } + break;*/ + default: + break; + } + return AUBIO_OK; +} + + +/** + * aubio_midi_receive_event + * + * \note This could be moved to a callback function defined in the main programs + */ +sint_t aubio_midi_receive_event(aubio_midi_player_t* player, aubio_midi_event_t* event) +{ + /* current time in seconds */ + //smpl_t print_time = player->msec_passed * 1e-3; + //smpl_t print_time = player->usec_passed * 1e-6; + switch (event->type) { + case NOTE_ON: + break; + case NOTE_OFF: + break; + default: + break; + } + return AUBIO_OK; +} diff --git a/ext/midi/midi_player.h b/ext/midi/midi_player.h new file mode 100644 index 00000000..b82c3105 --- /dev/null +++ b/ext/midi/midi_player.h @@ -0,0 +1,69 @@ +/* + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA + */ + +/* this file originally taken from FluidSynth - A Software Synthesizer + * Copyright (C) 2003 Peter Hanappe and others. + */ + +/** \file + * midi player + */ + + +#ifndef _AUBIO_MIDI_PLAYER_H +#define _AUBIO_MIDI_PLAYER_H + +#define AUBIO_MIDI_PLAYER_MAX_TRACKS 128 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _aubio_midi_player_t aubio_midi_player_t; + + +aubio_midi_player_t* new_aubio_midi_player(void); +sint_t del_aubio_midi_player(aubio_midi_player_t* player); +sint_t aubio_midi_player_reset(aubio_midi_player_t* player); +sint_t aubio_midi_player_add_track(aubio_midi_player_t* player, aubio_track_t* track); +sint_t aubio_midi_player_count_tracks(aubio_midi_player_t* player); +aubio_track_t* aubio_midi_player_get_track(aubio_midi_player_t* player, sint_t i); +sint_t aubio_midi_player_add(aubio_midi_player_t* player, char* midifile); +sint_t aubio_midi_player_load(aubio_midi_player_t* player, char *filename); +sint_t aubio_midi_player_callback(void* data, uint_t msec); +sint_t aubio_midi_player_play(aubio_midi_player_t* player); +sint_t aubio_midi_player_play_offline(aubio_midi_player_t* player); +sint_t aubio_midi_player_stop(aubio_midi_player_t* player); +sint_t aubio_midi_player_set_loop(aubio_midi_player_t* player, sint_t loop); +sint_t aubio_midi_player_set_midi_tempo(aubio_midi_player_t* player, sint_t tempo); +sint_t aubio_midi_player_set_bpm(aubio_midi_player_t* player, sint_t bpm); +sint_t aubio_midi_player_join(aubio_midi_player_t* player); + +sint_t aubio_track_send_events(aubio_track_t* track, +/* aubio_synth_t* synth, */ + aubio_midi_player_t* player, + uint_t ticks); + +sint_t aubio_midi_send_event(aubio_midi_player_t* player, aubio_midi_event_t* event); +sint_t aubio_midi_receive_event(aubio_midi_player_t* player, aubio_midi_event_t* event); + +#ifdef __cplusplus +} +#endif + +#endif /* _AUBIO_MIDI_PLAYER_H*/ diff --git a/ext/midi/midi_track.c b/ext/midi/midi_track.c new file mode 100644 index 00000000..324c999f --- /dev/null +++ b/ext/midi/midi_track.c @@ -0,0 +1,162 @@ +/* + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA + */ + +/* this file originally taken from FluidSynth - A Software Synthesizer + * Copyright (C) 2003 Peter Hanappe and others. + */ + + +#include "aubio_priv.h" +#include "midi.h" +#include "midi_event.h" +#include "midi_track.h" +#include "midi_player.h" + + +/** new_aubio_track */ +aubio_track_t* new_aubio_track(int num) +{ + aubio_track_t* track; + track = AUBIO_NEW(aubio_track_t); + if (track == NULL) { + return NULL; + } + track->name = NULL; + track->num = num; + track->first = NULL; + track->cur = NULL; + track->last = NULL; + track->ticks = 0; + return track; +} + +/** del_aubio_track */ +int del_aubio_track(aubio_track_t* track) +{ + if (track->name != NULL) { + AUBIO_FREE(track->name); + } + if (track->first != NULL) { + del_aubio_midi_event(track->first); + } + AUBIO_FREE(track); + return AUBIO_OK; +} + +/** aubio_track_set_name */ +int aubio_track_set_name(aubio_track_t* track, char* name) +{ + int len; + if (track->name != NULL) { + AUBIO_FREE(track->name); + } + if (name == NULL) { + track->name = NULL; + return AUBIO_OK; + } + len = AUBIO_STRLEN(name); + track->name = AUBIO_MALLOC(len + 1); + if (track->name == NULL) { + AUBIO_ERR( "Out of memory"); + return AUBIO_FAIL; + } + AUBIO_STRCPY(track->name, name); + return AUBIO_OK; +} + +/** aubio_track_get_name */ +char* aubio_track_get_name(aubio_track_t* track) +{ + return track->name; +} + +/** aubio_track_get_duration */ +int aubio_track_get_duration(aubio_track_t* track) + { + int time = 0; + aubio_midi_event_t* evt = track->first; + while (evt != NULL) { + time += evt->dtime; + evt = evt->next; + } + return time; +} + +/** aubio_track_count_events */ +int aubio_track_count_events(aubio_track_t* track, int* on, int* off) +{ + aubio_midi_event_t* evt = track->first; + while (evt != NULL) { + if (evt->type == NOTE_ON) { + (*on)++; + } else if (evt->type == NOTE_OFF) { + (*off)++; + } + evt = evt->next; + } + return AUBIO_OK; +} + +/* + * aubio_track_add_event + */ +int aubio_track_add_event(aubio_track_t* track, aubio_midi_event_t* evt) +{ + evt->next = NULL; + if (track->first == NULL) { + track->first = evt; + track->cur = evt; + track->last = evt; + } else { + track->last->next = evt; + track->last = evt; + } + return AUBIO_OK; +} + +/* + * aubio_track_first_event + */ +aubio_midi_event_t* aubio_track_first_event(aubio_track_t* track) +{ + track->cur = track->first; + return track->cur; +} + +/* + * aubio_track_next_event + */ +aubio_midi_event_t* aubio_track_next_event(aubio_track_t* track) +{ + if (track->cur != NULL) { + track->cur = track->cur->next; + } + return track->cur; +} + +/* + * aubio_track_reset + */ + int +aubio_track_reset(aubio_track_t* track) +{ + track->ticks = 0; + track->cur = track->first; + return AUBIO_OK; +} + diff --git a/ext/midi/midi_track.h b/ext/midi/midi_track.h new file mode 100644 index 00000000..63f21962 --- /dev/null +++ b/ext/midi/midi_track.h @@ -0,0 +1,67 @@ +/* + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA + */ + +/* this file originally taken from FluidSynth - A Software Synthesizer + * Copyright (C) 2003 Peter Hanappe and others. + */ + +#ifndef _AUBIO_MIDI_TRACK_H +#define _AUBIO_MIDI_TRACK_H + +/** \file + * midi track structure + * + * \bug need public declaration ? + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** aubio_track_t */ +struct _aubio_track_t { + char* name; + int num; + aubio_midi_event_t *first; + aubio_midi_event_t *cur; + aubio_midi_event_t *last; + unsigned int ticks; +}; + +typedef struct _aubio_track_t aubio_track_t; + +aubio_track_t* new_aubio_track(int num); +int del_aubio_track(aubio_track_t* track); +int aubio_track_set_name(aubio_track_t* track, char* name); +char* aubio_track_get_name(aubio_track_t* track); +int aubio_track_add_event(aubio_track_t* track, aubio_midi_event_t* evt); +aubio_midi_event_t* aubio_track_first_event(aubio_track_t* track); +aubio_midi_event_t* aubio_track_next_event(aubio_track_t* track); +int aubio_track_get_duration(aubio_track_t* track); +int aubio_track_reset(aubio_track_t* track); +int aubio_track_count_events(aubio_track_t* track, int* on, int* off); + + +#define aubio_track_eot(track) ((track)->cur == NULL) + + +#ifdef __cplusplus +} +#endif + +#endif /*_AUBIO_MIDI_TRACK_H*/ diff --git a/ext/midi/timer.c b/ext/midi/timer.c new file mode 100644 index 00000000..f78fe096 --- /dev/null +++ b/ext/midi/timer.c @@ -0,0 +1,551 @@ +/* + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA + */ + +/* this file originally taken from FluidSynth - A Software Synthesizer + * Copyright (C) 2003 Peter Hanappe and others. + */ + +#include "aubio_priv.h" +#include "timer.h" + +#if defined(WIN32) + +/*=============================================================*/ +/* */ +/* Win32 */ +/* */ +/*=============================================================*/ + +/*************************************************************** + * + * Timer + * + */ +#include + +#if 0 +#include + +struct _aubio_timer_t +{ + long msec; + aubio_timer_callback_t callback; + void* data; + HANDLE thread; + DWORD thread_id; + int cont; + int auto_destroy; +}; + +static int aubio_timer_count = 0; +DWORD WINAPI aubio_timer_run(LPVOID data); + +aubio_timer_t* +new_aubio_timer(int msec, aubio_timer_callback_t callback, void* data, + int new_thread, int auto_destroy) +{ + aubio_timer_t* timer = AUBIO_NEW(aubio_timer_t); + if (timer == NULL) { + AUBIO_ERR( "Out of memory"); + return NULL; + } + + timer->cont = 1; + timer->msec = msec; + timer->callback = callback; + timer->data = data; + timer->thread = 0; + timer->auto_destroy = auto_destroy; + + if (new_thread) { + timer->thread = CreateThread(NULL, 0, aubio_timer_run, (LPVOID) timer, 0, &timer->thread_id); + if (timer->thread == NULL) { + AUBIO_ERR( "Couldn't create timer thread"); + AUBIO_FREE(timer); + return NULL; + } + SetThreadPriority(timer->thread, THREAD_PRIORITY_TIME_CRITICAL); + } else { + aubio_timer_run((LPVOID) timer); + } + return timer; +} + +DWORD WINAPI +aubio_timer_run(LPVOID data) +{ + int count = 0; + int cont = 1; + long start; + long delay; + aubio_timer_t* timer; + timer = (aubio_timer_t*) data; + + if ((timer == NULL) || (timer->callback == NULL)) { + return 0; + } + + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); + + /* keep track of the start time for absolute positioning */ + start = aubio_curtime(); + + while (cont) { + + /* do whatever we have to do */ + cont = (*timer->callback)(timer->data, aubio_curtime() - start); + + count++; + + /* to avoid incremental time errors, I calculate the delay between + two callbacks bringing in the "absolute" time (count * + timer->msec) */ + delay = (count * timer->msec) - (aubio_curtime() - start); + if (delay > 0) { + Sleep(delay); + } + + cont &= timer->cont; + } + + AUBIO_DBG( "Timer thread finished"); + + if (timer->auto_destroy) { + AUBIO_FREE(timer); + } + + ExitThread(0); + return 0; +} + +int +delete_aubio_timer(aubio_timer_t* timer) +{ + timer->cont = 0; + aubio_timer_join(timer); + AUBIO_FREE(timer); + return AUBIO_OK; +} + +int +aubio_timer_join(aubio_timer_t* timer) +{ + DWORD wait_result; + if (timer->thread == 0) { + return AUBIO_OK; + } + wait_result = WaitForSingleObject(timer->thread, INFINITE); + return (wait_result == WAIT_OBJECT_0)? AUBIO_OK : AUBIO_FAIL; +} +/*************************************************************** + * + * Time + */ + +double rdtsc(void); +double aubio_estimate_cpu_frequency(void); + +static double aubio_cpu_frequency = -1.0; + +void aubio_time_config(void) +{ + if (aubio_cpu_frequency < 0.0) { + aubio_cpu_frequency = aubio_estimate_cpu_frequency() / 1000000.0; + } +} + +double aubio_utime(void) +{ + return (rdtsc() / aubio_cpu_frequency); +} + +double rdtsc(void) +{ + LARGE_INTEGER t; + QueryPerformanceCounter(&t); + return (double) t.QuadPart; +} + +double aubio_estimate_cpu_frequency(void) +{ +#if 0 + LONGLONG start, stop, ticks; + unsigned int before, after, delta; + double freq; + + start = rdtsc(); + stop = start; + before = aubio_curtime(); + after = before; + + while (1) { + if (after - before > 1000) { + break; + } + after = aubio_curtime(); + stop = rdtsc(); + } + + delta = after - before; + ticks = stop - start; + + freq = 1000 * ticks / delta; + + return freq; + +#else + unsigned int before, after; + LARGE_INTEGER start, stop; + + before = aubio_curtime(); + QueryPerformanceCounter(&start); + + Sleep(1000); + + after = aubio_curtime(); + QueryPerformanceCounter(&stop); + + return (double) 1000 * (stop.QuadPart - start.QuadPart) / (after - before); +#endif +} + +#endif + + +#elif defined(MACOS9) +/*=============================================================*/ +/* */ +/* MacOS 9 */ +/* */ +/*=============================================================*/ + + +/*************************************************************** + * + * Timer + */ + +struct _aubio_timer_t +{ + TMTask myTmTask; + long msec; + unsigned int start; + unsigned int count; + int isInstalled; + aubio_timer_callback_t callback; + void* data; + int auto_destroy; +}; + +static TimerUPP myTimerUPP; + +void +_timerCallback(aubio_timer_t *timer) +{ + int cont; + cont = (*timer->callback)(timer->data, aubio_curtime() - timer->start); + if (cont) { + PrimeTime((QElemPtr)timer, timer->msec); + } else { + timer->isInstalled = 0; + } + timer->count++; +} + +aubio_timer_t* +new_aubio_timer(int msec, aubio_timer_callback_t callback, void* data, + int new_thread, int auto_destroy) +{ + aubio_timer_t* timer = AUBIO_NEW(aubio_timer_t); + if (timer == NULL) { + AUBIO_ERR( "Out of memory"); + return NULL; + } + + if (!myTimerUPP) + myTimerUPP = NewTimerProc(_timerCallback); + + /* setup tmtask */ + timer->myTmTask.tmAddr = myTimerUPP; + timer->myTmTask.qLink = NULL; + timer->myTmTask.qType = 0; + timer->myTmTask.tmCount = 0L; + timer->myTmTask.tmWakeUp = 0L; + timer->myTmTask.tmReserved = 0L; + + timer->callback = callback; + + timer->msec = msec; + timer->data = data; + timer->start = aubio_curtime(); + timer->isInstalled = 1; + timer->count = 0; + timer->auto_destroy = auto_destroy; + + InsXTime((QElemPtr)timer); + PrimeTime((QElemPtr)timer, msec); + + return timer; +} + +int +delete_aubio_timer(aubio_timer_t* timer) +{ + if (timer->isInstalled) { + RmvTime((QElemPtr)timer); + } + AUBIO_FREE(timer); + return AUBIO_OK; +} + +int +aubio_timer_join(aubio_timer_t* timer) +{ + if (timer->isInstalled) { + int count = timer->count; + /* wait until count has incremented */ + while (count == timer->count) {} + } + return AUBIO_OK; +} + +/*************************************************************** + * + * Time + */ +#define kTwoPower32 (4294967296.0) /* 2^32 */ + +void aubio_time_config(void) +{ +} + +unsigned int aubio_curtime() +{ + /* could be optimized by not going though a double */ + UnsignedWide uS; + double mSf; + unsigned int ms; + + Microseconds(&uS); + + mSf = ((((double) uS.hi) * kTwoPower32) + uS.lo)/1000.0f; + + ms = mSf; + + return (ms); +} + + + +#else + +/*=============================================================*/ +/* */ +/* POSIX */ +/* */ +/*=============================================================*/ + +#include +#include +#include + + +/*************************************************************** + * + * Timer + */ + +struct _aubio_timer_t +{ + long msec; + aubio_timer_callback_t callback; + void* data; + pthread_t thread; + int cont; + int auto_destroy; +}; + +void* +aubio_timer_start(void *data) +{ + int count = 0; + int cont = 1; + long start; + long delay; + aubio_timer_t* timer; + timer = (aubio_timer_t*) data; + + /* keep track of the start time for absolute positioning */ + start = aubio_curtime(); + + while (cont) { + + /* do whatever we have to do */ + cont = (*timer->callback)(timer->data, aubio_curtime() - start); + + count++; + + /* to avoid incremental time errors, calculate the delay between + two callbacks bringing in the "absolute" time (count * + timer->msec) */ + delay = (count * timer->msec) - (aubio_curtime() - start); + if (delay > 0) { + usleep(delay * 1000); + } + + cont &= timer->cont; + } + + AUBIO_DBG( "Timer thread finished"); + if (timer->thread != 0) { + pthread_exit(NULL); + } + + if (timer->auto_destroy) { + AUBIO_FREE(timer); + } + + return NULL; +} + +aubio_timer_t* +new_aubio_timer(int msec, aubio_timer_callback_t callback, void* data, + int new_thread, int auto_destroy) +{ + aubio_timer_t* timer = AUBIO_NEW(aubio_timer_t); + if (timer == NULL) { + AUBIO_ERR( "Out of memory"); + return NULL; + } + timer->msec = msec; + timer->callback = callback; + timer->data = data; + timer->cont = 1; + timer->thread = 0; + timer->auto_destroy = auto_destroy; + + if (new_thread) { + if (pthread_create(&timer->thread, NULL, aubio_timer_start, (void*) timer)) { + AUBIO_ERR( "Failed to create the timer thread"); + AUBIO_FREE(timer); + return NULL; + } + } else { + aubio_timer_start((void*) timer); + } + return timer; +} + +int +delete_aubio_timer(aubio_timer_t* timer) +{ + timer->cont = 0; + aubio_timer_join(timer); + AUBIO_DBG( "Deleted player thread\n"); + AUBIO_FREE(timer); + return AUBIO_OK; +} + +int +aubio_timer_join(aubio_timer_t* timer) +{ + int err = 0; + + if (timer->thread != 0) { + err = pthread_join(timer->thread, NULL); + } else + AUBIO_DBG( "Joined player thread\n"); + return (err == 0)? AUBIO_OK : AUBIO_FAIL; +} + + +/*************************************************************** + * + * Time + */ + +static double aubio_cpu_frequency = -1.0; + +double rdtsc(void); +double aubio_estimate_cpu_frequency(void); + +void aubio_time_config(void) +{ + if (aubio_cpu_frequency < 0.0) { + aubio_cpu_frequency = aubio_estimate_cpu_frequency() / 1000000.0; + } +} + +unsigned int aubio_curtime() +{ + struct timeval now; + gettimeofday(&now, NULL); + return now.tv_sec * 1000 + now.tv_usec / 1000; +} + +double aubio_utime(void) +{ + return (rdtsc() / aubio_cpu_frequency); +} + +#if !defined(__i386__) + +double rdtsc(void) +{ + return 0.0; +} + +double aubio_estimate_cpu_frequency(void) +{ + return 1.0; +} + +#else + +double rdtsc(void) +{ + unsigned int a, b; + + __asm__ ("rdtsc" : "=a" (a), "=d" (b)); + return (double)b * (double)0x10000 * (double)0x10000 + a; +} + +double aubio_estimate_cpu_frequency(void) +{ + double start, stop; + unsigned int a0, b0, a1, b1; + unsigned int before, after; + + before = aubio_curtime(); + __asm__ ("rdtsc" : "=a" (a0), "=d" (b0)); + + sleep(1); + + after = aubio_curtime(); + __asm__ ("rdtsc" : "=a" (a1), "=d" (b1)); + + + start = (double)b0 * (double)0x10000 * (double)0x10000 + a0; + stop = (double)b1 * (double)0x10000 * (double)0x10000 + a1; + + return 1000 * (stop - start) / (after - before); +} + +#endif + +#endif diff --git a/ext/midi/timer.h b/ext/midi/timer.h new file mode 100644 index 00000000..582fe925 --- /dev/null +++ b/ext/midi/timer.h @@ -0,0 +1,34 @@ + +#if defined(WIN32) +#define aubio_curtime() GetTickCount() + +double aubio_utime(void); + +#elif defined(MACOS9) +#include +#include + +unsigned int aubio_curtime(); +#define aubio_utime() 0.0 + +#else + +unsigned int aubio_curtime(void); +double aubio_utime(void); + +#endif + +/* if the callback function returns 1 the timer will continue; if it + returns 0 it will stop */ +typedef int (*aubio_timer_callback_t)(void* data, unsigned int msec); + +typedef struct _aubio_timer_t aubio_timer_t; + +aubio_timer_t* new_aubio_timer(int msec, aubio_timer_callback_t callback, + void* data, int new_thread, int auto_destroy); + +int delete_aubio_timer(aubio_timer_t* timer); +int aubio_timer_join(aubio_timer_t* timer); +int aubio_timer_stop(aubio_timer_t* timer); +void * aubio_timer_start(void * data); +void aubio_time_config(void); diff --git a/src/Makefile.am b/src/Makefile.am index add28fc8..1311c530 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -19,16 +19,7 @@ pkginclude_HEADERS = aubio.h \ pitchdetection.h \ pitchmcomb.h \ pitchyin.h \ - filter.h \ - midi.h \ - list.h \ - timer.h \ - midi_file.h \ - midi_driver.h \ - midi_event.h \ - midi_track.h \ - midi_player.h \ - midi_parser.h + filter.h lib_LTLIBRARIES = libaubio.la libaubio_la_SOURCES = aubio.h \ @@ -66,27 +57,7 @@ libaubio_la_SOURCES = aubio.h \ pitchyin.c \ pitchyin.h \ filter.c \ - filter.h \ - midi.c \ - midi.h \ - list.c \ - list.h \ - timer.c \ - timer.h \ - midi_alsa_seq.c \ - midi_alsa_raw.c \ - midi_file.c \ - midi_file.h \ - midi_event.c \ - midi_event.h \ - midi_track.c \ - midi_track.h \ - midi_player.c \ - midi_player.h \ - midi_parser.c \ - midi_parser.h \ - midi_driver.h \ - midi_driver.c + filter.h -AM_CFLAGS = @SNDLIB_CFLAGS@ @JACK_CFLAGS@ @FFTWLIB_CFLAGS@ @SAMPLERATE_CFLAGS@ @ALSA_CFLAGS@ @LADCCA_CFLAGS@ -libaubio_la_LIBADD = @SNDLIB_LIBS@ @JACK_LIBS@ @FFTWLIB_LIBS@ @SAMPLERATE_LIBS@ @ALSA_LIBS@ @LADCCA_LIBS@ @LTLIBOBJS@ +AM_CFLAGS = @SNDLIB_CFLAGS@ @JACK_CFLAGS@ @FFTWLIB_CFLAGS@ @SAMPLERATE_CFLAGS@ @LADCCA_CFLAGS@ +libaubio_la_LIBADD = @SNDLIB_LIBS@ @JACK_LIBS@ @FFTWLIB_LIBS@ @SAMPLERATE_LIBS@ @LADCCA_LIBS@ @LTLIBOBJS@ diff --git a/src/Makefile.in b/src/Makefile.in index c90116cc..308797f2 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -172,16 +172,7 @@ pkginclude_HEADERS = aubio.h \ pitchdetection.h \ pitchmcomb.h \ pitchyin.h \ - filter.h \ - midi.h \ - list.h \ - timer.h \ - midi_file.h \ - midi_driver.h \ - midi_event.h \ - midi_track.h \ - midi_player.h \ - midi_parser.h + filter.h lib_LTLIBRARIES = libaubio.la @@ -220,31 +211,11 @@ libaubio_la_SOURCES = aubio.h \ pitchyin.c \ pitchyin.h \ filter.c \ - filter.h \ - midi.c \ - midi.h \ - list.c \ - list.h \ - timer.c \ - timer.h \ - midi_alsa_seq.c \ - midi_alsa_raw.c \ - midi_file.c \ - midi_file.h \ - midi_event.c \ - midi_event.h \ - midi_track.c \ - midi_track.h \ - midi_player.c \ - midi_player.h \ - midi_parser.c \ - midi_parser.h \ - midi_driver.h \ - midi_driver.c - - -AM_CFLAGS = @SNDLIB_CFLAGS@ @JACK_CFLAGS@ @FFTWLIB_CFLAGS@ @SAMPLERATE_CFLAGS@ @ALSA_CFLAGS@ @LADCCA_CFLAGS@ -libaubio_la_LIBADD = @SNDLIB_LIBS@ @JACK_LIBS@ @FFTWLIB_LIBS@ @SAMPLERATE_LIBS@ @ALSA_LIBS@ @LADCCA_LIBS@ @LTLIBOBJS@ + filter.h + + +AM_CFLAGS = @SNDLIB_CFLAGS@ @JACK_CFLAGS@ @FFTWLIB_CFLAGS@ @SAMPLERATE_CFLAGS@ @LADCCA_CFLAGS@ +libaubio_la_LIBADD = @SNDLIB_LIBS@ @JACK_LIBS@ @FFTWLIB_LIBS@ @SAMPLERATE_LIBS@ @LADCCA_LIBS@ @LTLIBOBJS@ subdir = src ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs @@ -257,9 +228,7 @@ libaubio_la_DEPENDENCIES = @LTLIBOBJS@ am_libaubio_la_OBJECTS = jackio.lo phasevoc.lo sndfileio.lo mathutils.lo \ fft.lo sample.lo hist.lo scale.lo resample.lo onsetdetection.lo \ tss.lo peakpick.lo biquad.lo pitchdetection.lo pitchmcomb.lo \ - pitchyin.lo filter.lo midi.lo list.lo timer.lo midi_alsa_seq.lo \ - midi_alsa_raw.lo midi_file.lo midi_event.lo midi_track.lo \ - midi_player.lo midi_parser.lo midi_driver.lo + pitchyin.lo filter.lo libaubio_la_OBJECTS = $(am_libaubio_la_OBJECTS) DEFAULT_INCLUDES = -I. -I$(srcdir) -I. @@ -267,23 +236,14 @@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles @AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/biquad.Plo ./$(DEPDIR)/fft.Plo \ @AMDEP_TRUE@ ./$(DEPDIR)/filter.Plo ./$(DEPDIR)/hist.Plo \ -@AMDEP_TRUE@ ./$(DEPDIR)/jackio.Plo ./$(DEPDIR)/list.Plo \ -@AMDEP_TRUE@ ./$(DEPDIR)/mathutils.Plo ./$(DEPDIR)/midi.Plo \ -@AMDEP_TRUE@ ./$(DEPDIR)/midi_alsa_raw.Plo \ -@AMDEP_TRUE@ ./$(DEPDIR)/midi_alsa_seq.Plo \ -@AMDEP_TRUE@ ./$(DEPDIR)/midi_driver.Plo \ -@AMDEP_TRUE@ ./$(DEPDIR)/midi_event.Plo \ -@AMDEP_TRUE@ ./$(DEPDIR)/midi_file.Plo \ -@AMDEP_TRUE@ ./$(DEPDIR)/midi_parser.Plo \ -@AMDEP_TRUE@ ./$(DEPDIR)/midi_player.Plo \ -@AMDEP_TRUE@ ./$(DEPDIR)/midi_track.Plo \ +@AMDEP_TRUE@ ./$(DEPDIR)/jackio.Plo ./$(DEPDIR)/mathutils.Plo \ @AMDEP_TRUE@ ./$(DEPDIR)/onsetdetection.Plo \ @AMDEP_TRUE@ ./$(DEPDIR)/peakpick.Plo ./$(DEPDIR)/phasevoc.Plo \ @AMDEP_TRUE@ ./$(DEPDIR)/pitchdetection.Plo \ @AMDEP_TRUE@ ./$(DEPDIR)/pitchmcomb.Plo ./$(DEPDIR)/pitchyin.Plo \ @AMDEP_TRUE@ ./$(DEPDIR)/resample.Plo ./$(DEPDIR)/sample.Plo \ @AMDEP_TRUE@ ./$(DEPDIR)/scale.Plo ./$(DEPDIR)/sndfileio.Plo \ -@AMDEP_TRUE@ ./$(DEPDIR)/timer.Plo ./$(DEPDIR)/tss.Plo +@AMDEP_TRUE@ ./$(DEPDIR)/tss.Plo COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \ @@ -367,17 +327,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/filter.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hist.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/jackio.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/list.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mathutils.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/midi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/midi_alsa_raw.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/midi_alsa_seq.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/midi_driver.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/midi_event.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/midi_file.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/midi_parser.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/midi_player.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/midi_track.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/onsetdetection.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/peakpick.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/phasevoc.Plo@am__quote@ @@ -388,7 +338,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sample.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scale.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sndfileio.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tss.Plo@am__quote@ .c.o: diff --git a/src/aubio.h b/src/aubio.h index f0f9c61e..31efae2c 100644 --- a/src/aubio.h +++ b/src/aubio.h @@ -19,46 +19,16 @@ /** @mainpage * - * \section whatis All starts here ... + * \section whatis Introduction * - * Aubio (note i need another name for this program) is a small library - * for audio and control processing. The aim of this project is educative - * (for me, and all the others who might want to use it). The main purpose of - * aubio is to experiment with some bleeding-edge algorithms in a real time - * context. This library targets at being light and portable, and relatively - * fast. - * - * aubio is implemented as a library of C units and functions. You can create - * all the C objects you need in your processing function, process those - * objects from a main callback function, and delete them when done. This - * simple but efficient way makes it easy to write a small wrapper, for - * instance in the python language. (actually, GUIs should probably be build - * with python itself). Writing LADSPA, jmax, pd, or any other like audio - * plugins should be feasible too. - * - * Aubio provides various tools, some of them are listed below. I added the - * names of the original authors and references to corresponding articles - * are in the corresponding source file. - * - * - various maths tools - * - phase vocoder - * - up/downsampling - * - filtering (n pole/zero pairs) - * - onset detection functions - * - onset peak picking - * - multicomb-filtering pitch detection - * - transient/steady-state separation - * - audio and midi devices abstractions (callback) - * - audio and midi files abstractions (various access modes) - * - * The midi support is kindly borrowed from the powerful Fluidsynth, written - * by Peter Hanappe. - * - * See the README file for more information. + * Aubio is a library for audio labelling: it provides function for pitch + * estimation and onset detection. See the README file for more + * information. * * \section bugs bugs and todo * - * This software is under development. It needs debugging and optimisations. + * This software is under development. It needs debugging and + * optimisations. * * See bugs and todo lists. * @@ -109,14 +79,6 @@ extern "C" { #include "pitchmcomb.h" #include "pitchyin.h" -#include "midi.h" -#include "midi_event.h" -#include "midi_track.h" -#include "midi_player.h" -#include "midi_parser.h" -#include "midi_file.h" -#include "midi_driver.h" - #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/src/list.c b/src/list.c deleted file mode 100644 index c95220cb..00000000 --- a/src/list.c +++ /dev/null @@ -1,256 +0,0 @@ -/* GLIB - Library of useful routines for C programming - * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/* Modified by the GLib Team and others 1997-1999. See the AUTHORS - * file for a list of people on the GLib Team. See the ChangeLog - * files for a list of changes. These files are distributed with - * GLib at ftp://ftp.gtk.org/pub/gtk/. - */ - -#include "aubio_priv.h" -#include "list.h" - - - -aubio_list_t* -new_aubio_list(void) -{ - aubio_list_t* list; - list = AUBIO_NEW(aubio_list_t); - list->data = NULL; - list->next = NULL; - return list; -} - -void -del_aubio_list(aubio_list_t *list) -{ - aubio_list_t *next; - while (list) { - next = list->next; - AUBIO_FREE(list); - list = next; - } -} - -void -del_aubio_list1(aubio_list_t *list) -{ - if (list) { - AUBIO_FREE(list); - } -} - -aubio_list_t* -aubio_list_append(aubio_list_t *list, void* data) -{ - aubio_list_t *new_list; - aubio_list_t *last; - - new_list = new_aubio_list(); - new_list->data = data; - - if (list) - { - last = aubio_list_last(list); - /* g_assert (last != NULL); */ - last->next = new_list; - - return list; - } - else - return new_list; -} - -aubio_list_t* -aubio_list_prepend(aubio_list_t *list, void* data) -{ - aubio_list_t *new_list; - - new_list = new_aubio_list(); - new_list->data = data; - new_list->next = list; - - return new_list; -} - -aubio_list_t* -aubio_list_nth(aubio_list_t *list, int n) -{ - while ((n-- > 0) && list) { - list = list->next; - } - - return list; -} - -aubio_list_t* -aubio_list_remove(aubio_list_t *list, void* data) -{ - aubio_list_t *tmp; - aubio_list_t *prev; - - prev = NULL; - tmp = list; - - while (tmp) { - if (tmp->data == data) { - if (prev) { - prev->next = tmp->next; - } - if (list == tmp) { - list = list->next; - } - tmp->next = NULL; - del_aubio_list(tmp); - - break; - } - - prev = tmp; - tmp = tmp->next; - } - - return list; -} - -aubio_list_t* -aubio_list_remove_link(aubio_list_t *list, aubio_list_t *link) -{ - aubio_list_t *tmp; - aubio_list_t *prev; - - prev = NULL; - tmp = list; - - while (tmp) { - if (tmp == link) { - if (prev) { - prev->next = tmp->next; - } - if (list == tmp) { - list = list->next; - } - tmp->next = NULL; - break; - } - - prev = tmp; - tmp = tmp->next; - } - - return list; -} - -static aubio_list_t* -aubio_list_sort_merge(aubio_list_t *l1, aubio_list_t *l2, aubio_compare_func_t compare_func) -{ - aubio_list_t list, *l; - - l = &list; - - while (l1 && l2) { - if (compare_func(l1->data,l2->data) < 0) { - l = l->next = l1; - l1 = l1->next; - } else { - l = l->next = l2; - l2 = l2->next; - } - } - l->next= l1 ? l1 : l2; - - return list.next; -} - -aubio_list_t* -aubio_list_sort(aubio_list_t *list, aubio_compare_func_t compare_func) -{ - aubio_list_t *l1, *l2; - - if (!list) { - return NULL; - } - if (!list->next) { - return list; - } - - l1 = list; - l2 = list->next; - - while ((l2 = l2->next) != NULL) { - if ((l2 = l2->next) == NULL) - break; - l1=l1->next; - } - l2 = l1->next; - l1->next = NULL; - - return aubio_list_sort_merge(aubio_list_sort(list, compare_func), - aubio_list_sort(l2, compare_func), - compare_func); -} - - -aubio_list_t* -aubio_list_last(aubio_list_t *list) -{ - if (list) { - while (list->next) - list = list->next; - } - - return list; -} - -int -aubio_list_size(aubio_list_t *list) -{ - int n = 0; - while (list) { - n++; - list = list->next; - } - return n; -} - -aubio_list_t* aubio_list_insert_at(aubio_list_t *list, int n, void* data) -{ - aubio_list_t *new_list; - aubio_list_t *cur; - aubio_list_t *prev = NULL; - - new_list = new_aubio_list(); - new_list->data = data; - - cur = list; - while ((n-- > 0) && cur) { - prev = cur; - cur = cur->next; - } - - new_list->next = cur; - - if (prev) { - prev->next = new_list; - return list; - } else { - return new_list; - } -} diff --git a/src/list.h b/src/list.h deleted file mode 100644 index 3bcefd6a..00000000 --- a/src/list.h +++ /dev/null @@ -1,63 +0,0 @@ -/* GLIB - Library of useful routines for C programming - * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/** - * \file - * list of objects - * - * implement common list structure and its various functions - * - * adapted for audio by Paul Brossier - * - * Modified by the GLib Team and others 1997-1999. See the AUTHORS - * file for a list of people on the GLib Team. See the ChangeLog - * files for a list of changes. These files are distributed with - * GLib at ftp://ftp.gtk.org/pub/gtk/. - */ - -#ifndef _AUBIO_LIST_H -#define _AUBIO_LIST_H - -typedef struct _aubio_list_t aubio_list_t; - -struct _aubio_list_t -{ - void* data; - aubio_list_t *next; -}; - -typedef int (*aubio_compare_func_t)(void* a, void* b); - -aubio_list_t* new_aubio_list(void); -void del_aubio_list(aubio_list_t *list); -void del_aubio_list1(aubio_list_t *list); -aubio_list_t* aubio_list_sort(aubio_list_t *list, aubio_compare_func_t compare_func); -aubio_list_t* aubio_list_append(aubio_list_t *list, void* data); -aubio_list_t* aubio_list_prepend(aubio_list_t *list, void* data); -aubio_list_t* aubio_list_remove(aubio_list_t *list, void* data); -aubio_list_t* aubio_list_remove_link(aubio_list_t *list, aubio_list_t *llink); -aubio_list_t* aubio_list_nth(aubio_list_t *list, int n); -aubio_list_t* aubio_list_last(aubio_list_t *list); -aubio_list_t* aubio_list_insert_at(aubio_list_t *list, int n, void* data); -int aubio_list_size(aubio_list_t *list); - -#define aubio_list_next(slist) ((slist) ? (((aubio_list_t *)(slist))->next) : NULL) -#define aubio_list_get(slist) ((slist) ? ((slist)->data) : NULL) - -#endif /* _AUBIO_LIST_H */ diff --git a/src/midi.c b/src/midi.c deleted file mode 100644 index 6a6c3708..00000000 --- a/src/midi.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License - * as published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - * 02111-1307, USA - */ - -/* this file originally taken from FluidSynth - A Software Synthesizer - * Copyright (C) 2003 Peter Hanappe and others. - */ - -#include "aubio_priv.h" -#include "midi.h" -#include "midi_event.h" -#include "midi_track.h" -#include "midi_player.h" - -/* all outgoing user messages are stored in a global text buffer */ -#define MIDI_MESSAGE_LENGTH 1024 -char midi_message_buffer[MIDI_MESSAGE_LENGTH]; - diff --git a/src/midi.h b/src/midi.h deleted file mode 100644 index 4aaea597..00000000 --- a/src/midi.h +++ /dev/null @@ -1,190 +0,0 @@ -/* - * - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License - * as published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - * 02111-1307, USA - */ - -/* this file originally taken from fluidsynth, peter hanappe and others, - * adapted for aubio by paul brossier, - */ - - -/** \file - * midi header - * - * contains all (?) possible known midi messages. - * - * this file originally taken from fluidsynth, Peter Hanappe and others, - * adapted for aubio by Paul Brossier, - */ - -#ifndef _AUBIO_MIDI_H -#define _AUBIO_MIDI_H - -//typedef struct _aubio_midi_driver_t aubio_midi_driver_t; - -//int aubio_midi_send_event(aubio_synth_t* synth, aubio_player_t* player, aubio_midi_event_t* evt); - -//int aubio_midi_router_send_event(aubio_midi_router_t* router, aubio_midi_event_t* event); - - -/*************************************************************** - * - * CONSTANTS & ENUM - */ - -#ifdef __cplusplus -extern "C" { -#endif - -enum aubio_midi_event_type { - /* channel messages */ - NOTE_OFF = 0x80, - NOTE_ON = 0x90, - KEY_PRESSURE = 0xa0, - CONTROL_CHANGE = 0xb0, - PROGRAM_CHANGE = 0xc0, - CHANNEL_PRESSURE = 0xd0, - PITCH_BEND = 0xe0, - /* system exclusive */ - MIDI_SYSEX = 0xf0, - /* system common - never in midi files */ - MIDI_TIME_CODE = 0xf1, - MIDI_SONG_POSITION = 0xf2, - MIDI_SONG_SELECT = 0xf3, - MIDI_TUNE_REQUEST = 0xf6, - MIDI_EOX = 0xf7, - /* system real-time - never in midi files */ - MIDI_SYNC = 0xf8, - MIDI_TICK = 0xf9, - MIDI_START = 0xfa, - MIDI_CONTINUE = 0xfb, - MIDI_STOP = 0xfc, - MIDI_ACTIVE_SENSING = 0xfe, - MIDI_SYSTEM_RESET = 0xff, - /* meta event - for midi files only */ - MIDI_META_EVENT = 0xff -}; - -enum aubio_midi_control_change { - BANK_SELECT_MSB = 0x00, - MODULATION_MSB = 0x01, - BREATH_MSB = 0x02, - FOOT_MSB = 0x04, - PORTAMENTO_TIME_MSB = 0x05, - DATA_ENTRY_MSB = 0x06, - VOLUME_MSB = 0x07, - BALANCE_MSB = 0x08, - PAN_MSB = 0x0A, - EXPRESSION_MSB = 0x0B, - EFFECTS1_MSB = 0x0C, - EFFECTS2_MSB = 0x0D, - GPC1_MSB = 0x10, /* general purpose controller */ - GPC2_MSB = 0x11, - GPC3_MSB = 0x12, - GPC4_MSB = 0x13, - BANK_SELECT_LSB = 0x20, - MODULATION_WHEEL_LSB = 0x21, - BREATH_LSB = 0x22, - FOOT_LSB = 0x24, - PORTAMENTO_TIME_LSB = 0x25, - DATA_ENTRY_LSB = 0x26, - VOLUME_LSB = 0x27, - BALANCE_LSB = 0x28, - PAN_LSB = 0x2A, - EXPRESSION_LSB = 0x2B, - EFFECTS1_LSB = 0x2C, - EFFECTS2_LSB = 0x2D, - GPC1_LSB = 0x30, - GPC2_LSB = 0x31, - GPC3_LSB = 0x32, - GPC4_LSB = 0x33, - SUSTAIN_SWITCH = 0x40, - PORTAMENTO_SWITCH = 0x41, - SOSTENUTO_SWITCH = 0x42, - SOFT_PEDAL_SWITCH = 0x43, - LEGATO_SWITCH = 0x45, - HOLD2_SWITCH = 0x45, - SOUND_CTRL1 = 0x46, - SOUND_CTRL2 = 0x47, - SOUND_CTRL3 = 0x48, - SOUND_CTRL4 = 0x49, - SOUND_CTRL5 = 0x4A, - SOUND_CTRL6 = 0x4B, - SOUND_CTRL7 = 0x4C, - SOUND_CTRL8 = 0x4D, - SOUND_CTRL9 = 0x4E, - SOUND_CTRL10 = 0x4F, - GPC5 = 0x50, - GPC6 = 0x51, - GPC7 = 0x52, - GPC8 = 0x53, - PORTAMENTO_CTRL = 0x54, - EFFECTS_DEPTH1 = 0x5B, - EFFECTS_DEPTH2 = 0x5C, - EFFECTS_DEPTH3 = 0x5D, - EFFECTS_DEPTH4 = 0x5E, - EFFECTS_DEPTH5 = 0x5F, - DATA_ENTRY_INCR = 0x60, - DATA_ENTRY_DECR = 0x61, - NRPN_LSB = 0x62, - NRPN_MSB = 0x63, - RPN_LSB = 0x64, - RPN_MSB = 0x65, - ALL_SOUND_OFF = 0x78, - ALL_CTRL_OFF = 0x79, - LOCAL_CONTROL = 0x7A, - ALL_NOTES_OFF = 0x7B, - OMNI_OFF = 0x7C, - OMNI_ON = 0x7D, - POLY_OFF = 0x7E, - POLY_ON = 0x7F -}; - -enum midi_meta_event { - MIDI_COPYRIGHT = 0x02, - MIDI_TRACK_NAME = 0x03, - MIDI_INST_NAME = 0x04, - MIDI_LYRIC = 0x05, - MIDI_MARKER = 0x06, - MIDI_CUE_POINT = 0x07, - MIDI_EOT = 0x2f, - MIDI_SET_TEMPO = 0x51, - MIDI_SMPTE_OFFSET = 0x54, - MIDI_TIME_SIGNATURE = 0x58, - MIDI_KEY_SIGNATURE = 0x59, - MIDI_SEQUENCER_EVENT = 0x7f -}; - -enum aubio_player_status -{ - AUBIO_MIDI_PLAYER_READY, - AUBIO_MIDI_PLAYER_PLAYING, - AUBIO_MIDI_PLAYER_DONE -}; - -enum aubio_driver_status -{ - AUBIO_MIDI_READY, - AUBIO_MIDI_LISTENING, - AUBIO_MIDI_DONE -}; - -#ifdef __cplusplus -} -#endif - -#endif /* _AUBIO_MIDI_H */ diff --git a/src/midi_alsa_raw.c b/src/midi_alsa_raw.c deleted file mode 100644 index 1556d018..00000000 --- a/src/midi_alsa_raw.c +++ /dev/null @@ -1,308 +0,0 @@ -/* - * Copyright 2004 Paul Brossier - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License - * as published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - * 02111-1307, USA - */ - -/* this file originally taken from Fluidsynth, Peter Hanappe and others. */ - -/** \file - * Midi driver for the Advanced Linux Sound Architecture - */ - - -#include "aubio_priv.h" -#include "midi.h" -#include "midi_event.h" -#include "midi_parser.h" -#include "midi_driver.h" - -#if ALSA_SUPPORT - -#define ALSA_PCM_NEW_HW_PARAMS_API -#include -#include -#include -#include -#include -/* #include //perror is in stdio.h */ - -#include "config.h" - -#define AUBIO_ALSA_DEFAULT_MIDI_DEVICE "default" - -/** \bug double define? */ -#define AUBIO_ALSA_BUFFER_LENGTH 512 - -/* SCHED_FIFO priorities for ALSA threads (see pthread_attr_setschedparam) */ -#define ALSA_RAWMIDI_SCHED_PRIORITY 90 -#define ALSA_SEQ_SCHED_PRIORITY 90 - -/** aubio_midi_alsa_raw_driver_t */ -typedef struct { - aubio_midi_driver_t driver; - snd_rawmidi_t *rawmidi_in; - snd_rawmidi_t *rawmidi_out; - struct pollfd *pfd; - int npfd; - pthread_t thread; - int status; - unsigned char buffer[AUBIO_ALSA_BUFFER_LENGTH]; - aubio_midi_parser_t* parser; -} aubio_midi_alsa_raw_driver_t; - -aubio_midi_driver_t* new_aubio_midi_alsa_raw_driver(//aubio_settings_t* settings, - handle_midi_event_func_t handler, - void* event_handler_data); -int del_aubio_midi_alsa_raw_driver(aubio_midi_driver_t* p); -static void* aubio_midi_alsa_raw_run(void* d); - - -/************************************************************** - * - * Alsa MIDI driver - * - */ - -//void aubio_midi_alsa_raw_driver_settings(aubio_settings_t* settings) -//{ -// aubio_settings_register_str(settings, "midi.alsa.device", "default", 0, NULL, NULL); -//} - -/** new_aubio_midi_alsa_raw_driver */ -aubio_midi_driver_t* new_aubio_midi_alsa_raw_driver( - //aubio_settings_t* settings, - handle_midi_event_func_t handler, - void* data) -{ - int i, err; - aubio_midi_alsa_raw_driver_t* dev; - pthread_attr_t attr; - int sched = SCHED_FIFO; - struct sched_param priority; - int count; - struct pollfd *pfd = NULL; - char* device = NULL; - - /* not much use doing anything */ - if (handler == NULL) { - AUBIO_ERR("Invalid argument"); - return NULL; - } - - /* allocate the device */ - dev = AUBIO_NEW(aubio_midi_alsa_raw_driver_t); - if (dev == NULL) { - AUBIO_ERR( "Out of memory"); - return NULL; - } - AUBIO_MEMSET(dev, 0, sizeof(aubio_midi_alsa_raw_driver_t)); - - dev->driver.handler = handler; - dev->driver.data = data; - - /* allocate one event to store the input data */ - dev->parser = new_aubio_midi_parser(); - if (dev->parser == NULL) { - AUBIO_ERR( "Out of memory"); - goto error_recovery; - } - - /* get the device name. if none is specified, use the default device. */ - //aubio_settings_getstr(settings, "midi.alsa.device", &device); - if (device == NULL) { - device = "default"; - } - - /* open the hardware device. only use midi in. */ - if ((err = snd_rawmidi_open(&dev->rawmidi_in, NULL, device, SND_RAWMIDI_NONBLOCK)) < 0) { - //if ((err = snd_rawmidi_open(&dev->rawmidi_in, &dev->rawmidi_out, device, SND_RAWMIDI_NONBLOCK)) < 0) { - AUBIO_ERR( "Error opening ALSA raw MIDI IN port"); - goto error_recovery; - } - - /* get # of MIDI file descriptors */ - count = snd_rawmidi_poll_descriptors_count(dev->rawmidi_in); - if (count > 0) { /* make sure there are some */ - pfd = AUBIO_MALLOC(sizeof (struct pollfd) * count); - dev->pfd = AUBIO_MALLOC(sizeof (struct pollfd) * count); - /* grab file descriptor POLL info structures */ - count = snd_rawmidi_poll_descriptors(dev->rawmidi_in, pfd, count); - } - - /* copy the input FDs */ - for (i = 0; i < count; i++) { /* loop over file descriptors */ - if (pfd[i].events & POLLIN) { /* use only the input FDs */ - dev->pfd[dev->npfd].fd = pfd[i].fd; - dev->pfd[dev->npfd].events = POLLIN; - dev->pfd[dev->npfd].revents = 0; - dev->npfd++; - } - } - AUBIO_FREE(pfd); - - - - dev->status = AUBIO_MIDI_READY; - - /* create the midi thread */ - if (pthread_attr_init(&attr)) { - AUBIO_ERR( "Couldn't initialize midi thread attributes"); - goto error_recovery; - } - - /* Was: "use fifo scheduling. if it fails, use default scheduling." */ - /* Now normal scheduling is used by default for the MIDI thread. The reason is, - * that fluidsynth works better with low latencies under heavy load, if only the - * audio thread is prioritized. - * With MIDI at ordinary priority, that could result in individual notes being played - * a bit late. On the other hand, if the audio thread is delayed, an audible dropout - * is the result. - * To reproduce this: Edirol UA-1 USB-MIDI interface, four buffers - * with 45 samples each (roughly 4 ms latency), ravewave soundfont. -MN - */ - - /* Not so sure anymore. We're losing MIDI data, if we can't keep up with - * the speed it is generated. */ - /* AUBIO_MSG("Note: High-priority scheduling for the MIDI thread was intentionally disabled."); - sched=SCHED_OTHER;*/ - - while (1) { - err = pthread_attr_setschedpolicy(&attr, sched); - if (err) { - //AUBIO_LOG(AUBIO_WARN, "Couldn't set high priority scheduling for the MIDI input"); - AUBIO_MSG( "Couldn't set high priority scheduling for the MIDI input"); - if (sched == SCHED_FIFO) { - sched = SCHED_OTHER; - continue; - } else { - AUBIO_ERR( "Couldn't set scheduling policy."); - goto error_recovery; - } - } - - /* SCHED_FIFO will not be active without setting the priority */ - priority.sched_priority = (sched == SCHED_FIFO) ? - ALSA_RAWMIDI_SCHED_PRIORITY : 0; - pthread_attr_setschedparam (&attr, &priority); - err = pthread_create(&dev->thread, &attr, aubio_midi_alsa_raw_run, (void*) dev); - if (err) { - AUBIO_MSG( "Couldn't set high priority scheduling for the MIDI input"); - if (sched == SCHED_FIFO) { - sched = SCHED_OTHER; - continue; - } else { - AUBIO_ERR( "Couldn't create the midi thread."); - goto error_recovery; - } - } - break; - } - return (aubio_midi_driver_t*) dev; - -error_recovery: - del_aubio_midi_alsa_raw_driver((aubio_midi_driver_t*) dev); - return NULL; - -} - -/** del_aubio_midi_alsa_raw_driver */ -int del_aubio_midi_alsa_raw_driver(aubio_midi_driver_t* p) -{ - aubio_midi_alsa_raw_driver_t* dev; - - dev = (aubio_midi_alsa_raw_driver_t*) p; - if (dev == NULL) { - return AUBIO_OK; - } - - dev->status = AUBIO_MIDI_DONE; - - /* cancel the thread and wait for it before cleaning up */ - if (dev->thread) { - if (pthread_cancel(dev->thread)) { - AUBIO_ERR( "Failed to cancel the midi thread"); - return AUBIO_FAIL; - } - if (pthread_join(dev->thread, NULL)) { - AUBIO_ERR( "Failed to join the midi thread"); - return AUBIO_FAIL; - } - } - if (dev->rawmidi_in) { - snd_rawmidi_drain(dev->rawmidi_in); - snd_rawmidi_close(dev->rawmidi_in); - } - if (dev->rawmidi_out) { - snd_rawmidi_drain(dev->rawmidi_out); - snd_rawmidi_close(dev->rawmidi_in); - } - if (dev->parser != NULL) { - del_aubio_midi_parser(dev->parser); - } - AUBIO_FREE(dev); - return AUBIO_OK; -} - -/** aubio_midi_alsa_raw_run */ -void * aubio_midi_alsa_raw_run(void* d) -{ - int n, i; - aubio_midi_event_t* evt; - aubio_midi_alsa_raw_driver_t* dev = (aubio_midi_alsa_raw_driver_t*) d; - - /* make sure the other threads can cancel this thread any time */ - if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL)) { - AUBIO_ERR( "Failed to set the cancel state of the midi thread"); - pthread_exit(NULL); - } - if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) { - AUBIO_ERR( "Failed to set the cancel state of the midi thread"); - pthread_exit(NULL); - } - - /* go into a loop until someone tells us to stop */ - dev->status = AUBIO_MIDI_LISTENING; - while (dev->status == AUBIO_MIDI_LISTENING) { - - /* is there something to read? */ - /* use a 100 milliseconds timeout */ - n = poll(dev->pfd, dev->npfd, 100); - if (n < 0) { - perror("poll"); - } else if (n > 0) { - - /* read new data */ - n = snd_rawmidi_read(dev->rawmidi_in, dev->buffer, - AUBIO_ALSA_BUFFER_LENGTH); - if ((n < 0) && (n != -EAGAIN)) { - AUBIO_ERR( "Failed to read the midi input"); - dev->status = AUBIO_MIDI_DONE; - } - - /* let the parser convert the data into events */ - for (i = 0; i < n; i++) { - evt = aubio_midi_parser_parse(dev->parser, dev->buffer[i]); - if (evt != NULL) { - (*dev->driver.handler)(dev->driver.data, evt); - } - } - }; - } - pthread_exit(NULL); -} - -#endif /* #if ALSA_SUPPORT */ diff --git a/src/midi_alsa_seq.c b/src/midi_alsa_seq.c deleted file mode 100644 index cf556eb7..00000000 --- a/src/midi_alsa_seq.c +++ /dev/null @@ -1,419 +0,0 @@ -/* - * Copyright 2004 Paul Brossier - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License - * as published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - * 02111-1307, USA - */ - -/* this file originally taken from Fluidsynth, Peter Hanappe and others. */ - -/** \file - * Midi driver for the Advanced Linux Sound Architecture (sequencer mode) - */ - - -#include "aubio_priv.h" -#include "midi.h" -#include "midi_event.h" -#include "midi_parser.h" -#include "midi_driver.h" -#include "config.h" - -#if ALSA_SUPPORT - -#define ALSA_PCM_NEW_HW_PARAMS_API -#include -#include -#include -#include -#include -/* #include //perror is in stdio.h */ - -#define AUBIO_ALSA_DEFAULT_SEQ_DEVICE "default" - -#define AUBIO_ALSA_BUFFER_LENGTH 512 - -/* SCHED_FIFO priorities for ALSA threads (see pthread_attr_setschedparam) */ -#define ALSA_RAWMIDI_SCHED_PRIORITY 90 -#define ALSA_SEQ_SCHED_PRIORITY 90 - - -/** aubio_alsa_seq_driver_t */ -typedef struct { - aubio_midi_driver_t driver; - snd_seq_t *seq_handle; - int seq_port; - struct pollfd *pfd; - int npfd; - pthread_t thread; - int status; -} aubio_alsa_seq_driver_t; - -aubio_midi_driver_t* new_aubio_alsa_seq_driver(//aubio_settings_t* settings, - handle_midi_event_func_t handler, - void* data); -int del_aubio_alsa_seq_driver(aubio_midi_driver_t* p); -static void* aubio_alsa_seq_run(void* d); - -//void aubio_alsa_seq_driver_settings(aubio_settings_t* settings) -//{ -// aubio_settings_register_str(settings, "midi.alsa_seq.device", "default", 0, NULL, NULL); -// aubio_settings_register_str(settings, "midi.alsa_seq.id", "pid", 0, NULL, NULL); -//} - -/** new_aubio_alsa_seq_driver */ -aubio_midi_driver_t* new_aubio_alsa_seq_driver(//aubio_settings_t* settings, - handle_midi_event_func_t handler, void* data) -{ - int i, err; - aubio_alsa_seq_driver_t* dev; /**< object to return */ - pthread_attr_t attr; /**< sequencer thread */ - int sched = SCHED_FIFO; /**< default scheduling policy */ - struct sched_param priority; /**< scheduling priority settings */ - int count; /**< number of MIDI file descriptors */ - struct pollfd *pfd = NULL; /**< poll file descriptor array (copied in dev->pfd) */ - char* device = NULL; /**< the device name */ - char* id = NULL; - char full_id[64]; - char full_name[64]; - - /* not much use doing anything */ - if (handler == NULL) { - AUBIO_ERR( "Invalid argument"); - return NULL; - } - - /* allocate the device */ - dev = AUBIO_NEW(aubio_alsa_seq_driver_t); - if (dev == NULL) { - AUBIO_ERR( "Out of memory"); - return NULL; - } - AUBIO_MEMSET(dev, 0, sizeof(aubio_alsa_seq_driver_t)); - dev->seq_port = -1; - dev->driver.data = data; - dev->driver.handler = handler; - - /* get the device name. if none is specified, use the default device. */ - //aubio_settings_getstr(settings, "midi.alsa_seq.device", &device); - if (device == NULL) { - device = "default"; - } - - /* open the sequencer INPUT only, non-blocking */ - //if ((err = snd_seq_open(&dev->seq_handle, device, SND_SEQ_OPEN_INPUT, - if ((err = snd_seq_open(&dev->seq_handle, device, SND_SEQ_OPEN_DUPLEX, - SND_SEQ_NONBLOCK)) < 0) { - AUBIO_ERR( "Error opening ALSA sequencer"); - goto error_recovery; - } - - /* tell the ladcca server our client id */ -#ifdef LADCCA_SUPPORT - { - int enable_ladcca = 1; - //aubio_settings_getint (settings, "ladcca.enable", &enable_ladcca); - if (enable_ladcca) - cca_alsa_client_id (aubio_cca_client, snd_seq_client_id (dev->seq_handle)); - } -#endif /* LADCCA_SUPPORT */ - - /* get # of MIDI file descriptors */ - count = snd_seq_poll_descriptors_count(dev->seq_handle, POLLIN); - if (count > 0) { /* make sure there are some */ - pfd = AUBIO_MALLOC(sizeof (struct pollfd) * count); - dev->pfd = AUBIO_MALLOC(sizeof (struct pollfd) * count); - /* grab file descriptor POLL info structures */ - count = snd_seq_poll_descriptors(dev->seq_handle, pfd, count, POLLIN); - } - - for (i = 0; i < count; i++) { /* loop over file descriptors */ - /* copy the input FDs */ - if (pfd[i].events & POLLIN) { /* use only the input FDs */ - dev->pfd[dev->npfd].fd = pfd[i].fd; - dev->pfd[dev->npfd].events = POLLIN; - dev->pfd[dev->npfd].revents = 0; - dev->npfd++; - } - } - AUBIO_FREE(pfd); - - //aubio_settings_getstr(settings, "midi.alsa_seq.id", &id); - - if (id != NULL) { - if (AUBIO_STRCMP(id, "pid") == 0) { - snprintf(full_id, 64, "aubio (%d)", getpid()); - snprintf(full_name, 64, "aubio_port (%d)", getpid()); - } else { - snprintf(full_id, 64, "aubio (%s)", id); - snprintf(full_name, 64, "aubio_port (%s)", id); - } - } else { - snprintf(full_id, 64, "aubio"); - snprintf(full_name, 64, "aubio_port"); - } - - /* set the client name */ - snd_seq_set_client_name (dev->seq_handle, full_id); - - if ((dev->seq_port = snd_seq_create_simple_port (dev->seq_handle, - full_name, - SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE | - SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ | - SND_SEQ_PORT_CAP_DUPLEX, - SND_SEQ_PORT_TYPE_APPLICATION)) < 0) - { - AUBIO_ERR( "Error creating ALSA sequencer port"); - goto error_recovery; - } - - dev->status = AUBIO_MIDI_READY; - - /* create the midi thread */ - if (pthread_attr_init(&attr)) { - AUBIO_ERR( "Couldn't initialize midi thread attributes"); - goto error_recovery; - } - - /* use fifo scheduling. if it fails, use default scheduling. */ - while (1) { - err = pthread_attr_setschedpolicy(&attr, sched); - if (err) { - AUBIO_MSG( "Couldn't set high priority scheduling for the MIDI input"); - if (sched == SCHED_FIFO) { - sched = SCHED_OTHER; - continue; - } else { - AUBIO_ERR( "Couldn't set scheduling policy."); - goto error_recovery; - } - } - - /* SCHED_FIFO will not be active without setting the priority */ - priority.sched_priority = (sched == SCHED_FIFO) ? ALSA_SEQ_SCHED_PRIORITY : 0; - pthread_attr_setschedparam (&attr, &priority); - - err = pthread_create(&dev->thread, &attr, aubio_alsa_seq_run, (void*) dev); - if (err) { - AUBIO_ERR( "Couldn't set high priority scheduling for the MIDI input"); - if (sched == SCHED_FIFO) { - sched = SCHED_OTHER; - continue; - } else { - //AUBIO_LOG(AUBIO_PANIC, "Couldn't create the midi thread."); - AUBIO_ERR( "Couldn't create the midi thread."); - goto error_recovery; - } - } - break; - } - return (aubio_midi_driver_t*) dev; - - -error_recovery: - del_aubio_alsa_seq_driver((aubio_midi_driver_t*) dev); - return NULL; -} - -/** del_aubio_alsa_seq_driver */ -int del_aubio_alsa_seq_driver(aubio_midi_driver_t* p) -{ - aubio_alsa_seq_driver_t* dev; - - dev = (aubio_alsa_seq_driver_t*) p; - if (dev == NULL) { - return AUBIO_OK; - } - - dev->status = AUBIO_MIDI_DONE; - - /* cancel the thread and wait for it before cleaning up */ - if (dev->thread) { - if (pthread_cancel(dev->thread)) { - AUBIO_ERR( "Failed to cancel the midi thread"); - return AUBIO_FAIL; - } - if (pthread_join(dev->thread, NULL)) { - AUBIO_ERR( "Failed to join the midi thread"); - return AUBIO_FAIL; - } - } - if (dev->seq_port >= 0) { - snd_seq_delete_simple_port (dev->seq_handle, dev->seq_port); - } - if (dev->seq_handle) { - snd_seq_drain_output(dev->seq_handle); - snd_seq_close(dev->seq_handle); - } - AUBIO_FREE(dev); - return AUBIO_OK; -} - -/** aubio_alsa_seq_run */ -void* aubio_alsa_seq_run(void* d) -{ - int n;//, i; - snd_seq_event_t *seq_ev; - aubio_midi_event_t evt; - aubio_alsa_seq_driver_t* dev = (aubio_alsa_seq_driver_t*) d; - - /* make sure the other threads can cancel this thread any time */ - if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL)) { - AUBIO_ERR( "Failed to set the cancel state of the midi thread"); - pthread_exit(NULL); - } - if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) { - AUBIO_ERR( "Failed to set the cancel state of the midi thread"); - pthread_exit(NULL); - } - - /* go into a loop until someone tells us to stop */ - dev->status = AUBIO_MIDI_LISTENING; - while (dev->status == AUBIO_MIDI_LISTENING) { - - /* is there something to read? */ - n = poll(dev->pfd, dev->npfd, 1); /* use a 1 milliseconds timeout */ - if (n < 0) { - perror("poll"); - } else if (n > 0) { - - /* read new events from the midi input port */ - while ((n = snd_seq_event_input(dev->seq_handle, &seq_ev)) >= 0) - { - switch (seq_ev->type) - { - case SND_SEQ_EVENT_NOTEON: - evt.type = NOTE_ON; - evt.channel = seq_ev->data.note.channel; - evt.param1 = seq_ev->data.note.note; - evt.param2 = seq_ev->data.note.velocity; - break; - case SND_SEQ_EVENT_NOTEOFF: - evt.type = NOTE_OFF; - evt.channel = seq_ev->data.note.channel; - evt.param1 = seq_ev->data.note.note; - evt.param2 = seq_ev->data.note.velocity; - break; - case SND_SEQ_EVENT_KEYPRESS: - evt.type = KEY_PRESSURE; - evt.channel = seq_ev->data.note.channel; - evt.param1 = seq_ev->data.note.note; - evt.param2 = seq_ev->data.note.velocity; - break; - case SND_SEQ_EVENT_CONTROLLER: - evt.type = CONTROL_CHANGE; - evt.channel = seq_ev->data.control.channel; - evt.param1 = seq_ev->data.control.param; - evt.param2 = seq_ev->data.control.value; - break; - case SND_SEQ_EVENT_PITCHBEND: - evt.type = PITCH_BEND; - evt.channel = seq_ev->data.control.channel; - /* ALSA pitch bend is -8192 - 8191, we adjust it here */ - evt.param1 = seq_ev->data.control.value + 8192; - break; - case SND_SEQ_EVENT_PGMCHANGE: - evt.type = PROGRAM_CHANGE; - evt.channel = seq_ev->data.control.channel; - evt.param1 = seq_ev->data.control.value; - break; - case SND_SEQ_EVENT_CHANPRESS: - evt.type = CHANNEL_PRESSURE; - evt.channel = seq_ev->data.control.channel; - evt.param1 = seq_ev->data.control.value; - break; - default: - continue; /* unhandled event, next loop iteration */ - } - - /* send the events to the next link in the chain */ - (*dev->driver.handler)(dev->driver.data, &evt); - - /* dump input on output */ - //snd_seq_ev_set_source(new_ev, dev->seq_port); - //snd_seq_ev_set_dest(seq_ev,dev->seq_handle,dev->seq_client); - //snd_seq_ev_set_subs(new_ev); - //snd_seq_ev_set_direct(new_ev); - //snd_seq_event_output(dev->seq_handle, new_ev); - //snd_seq_drain_output(dev->seq_handle); - - } - } - - if ((n < 0) && (n != -EAGAIN)) { - AUBIO_ERR( "Error occured while reading ALSA sequencer events"); - dev->status = AUBIO_MIDI_DONE; - } - -// /* added by piem to handle new data to output */ -// while (/* get new data, but from where ??? (n = snd_seq_event_output(dev->seq_handle, seq_ev)) >= 0*/ ) -// { -// /* dump input on output */ -// snd_seq_ev_set_source(new_ev, dev->seq_port); -// //snd_seq_ev_set_dest(seq_ev,dev->seq_handle,dev->seq_client); -// snd_seq_ev_set_subs(new_ev); -// snd_seq_ev_set_direct(new_ev); -// snd_seq_event_output(dev->seq_handle, new_ev); -// snd_seq_drain_output(dev->seq_handle); -// } - - } - pthread_exit(NULL); -} - - -snd_seq_event_t ev; - -void aubio_midi_direct_output(aubio_midi_driver_t * d, aubio_midi_event_t * event) -{ - aubio_alsa_seq_driver_t* dev = (aubio_alsa_seq_driver_t*) d; - /* - if (pthread_join(dev->thread, NULL)) { - AUBIO_ERR( "Failed to join the midi thread"); - } - */ - switch(event->type) - { - case NOTE_ON: - ev.type = SND_SEQ_EVENT_NOTEON; - ev.data.note.channel = event->channel; - ev.data.note.note = event->param1; - ev.data.note.velocity = event->param2; - //AUBIO_ERR( "NOTE_ON %d\n", event->param1); - break; - case NOTE_OFF: - ev.type = SND_SEQ_EVENT_NOTEOFF; - ev.data.note.channel = event->channel; - ev.data.note.note = event->param1; - ev.data.note.velocity = event->param2; - //AUBIO_ERR( "NOTE_OFF %d\n", event->param1); - break; - default: - break; - } - if (ev.type == SND_SEQ_EVENT_NOTEOFF || ev.type == SND_SEQ_EVENT_NOTEON ) { - snd_seq_ev_set_subs(&ev); - snd_seq_ev_set_direct(&ev); - snd_seq_ev_set_source(&ev, dev->seq_port); - snd_seq_event_output_direct(dev->seq_handle, &ev); - } - /* - if (pthread_detach(dev->thread)) { - AUBIO_ERR( "Failed to leave the midi thread"); - } - */ -} - -#endif /* #if ALSA_SUPPORT */ diff --git a/src/midi_driver.c b/src/midi_driver.c deleted file mode 100644 index c1c4de40..00000000 --- a/src/midi_driver.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License - * as published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - * 02111-1307, USA - */ -/* This file originally tajke from - * FluidSynth - A Software Synthesizer - * - * Copyright (C) 2003 Peter Hanappe and others. - */ - -#include "aubio_priv.h" -#include "midi_event.h" -#include "midi_driver.h" -//#include "settings.h" - -/* - * aubio_mdriver_definition - */ -struct aubio_mdriver_definition_t { - char* name; - aubio_midi_driver_t* (*new)( - //aubio_settings_t* settings, - handle_midi_event_func_t event_handler, - void* event_handler_data); - int (*free)(aubio_midi_driver_t* p); - void (*settings)(aubio_settings_t* settings); -}; - - -/* ALSA */ -#if ALSA_SUPPORT -aubio_midi_driver_t* new_aubio_midi_alsa_raw_driver( - //aubio_settings_t* settings, - handle_midi_event_func_t handler, - void* event_handler_data); -int del_aubio_midi_alsa_raw_driver(aubio_midi_driver_t* p); -void aubio_midi_alsa_raw_driver_settings(aubio_settings_t* settings); - -aubio_midi_driver_t* new_aubio_alsa_seq_driver( - //aubio_settings_t* settings, - handle_midi_event_func_t handler, - void* event_handler_data); -int del_aubio_alsa_seq_driver(aubio_midi_driver_t* p); -void aubio_alsa_seq_driver_settings(aubio_settings_t* settings); -#endif - -/* OSS */ -#if OSS_SUPPORT -aubio_midi_driver_t* new_aubio_oss_midi_driver(aubio_settings_t* settings, - handle_midi_event_func_t handler, - void* event_handler_data); -int del_aubio_oss_midi_driver(aubio_midi_driver_t* p); -//void aubio_oss_midi_driver_settings(aubio_settings_t* settings); -#endif - -/* Windows MIDI service */ -#if WINMIDI_SUPPORT -aubio_midi_driver_t* new_aubio_winmidi_driver(aubio_settings_t* settings, - handle_midi_event_func_t handler, - void* event_handler_data); -int del_aubio_winmidi_driver(aubio_midi_driver_t* p); -#endif - -/* definitions for the MidiShare driver */ -#if MIDISHARE_SUPPORT -aubio_midi_driver_t* new_aubio_midishare_midi_driver(aubio_settings_t* settings, - handle_midi_event_func_t handler, - void* event_handler_data); -int del_aubio_midishare_midi_driver(aubio_midi_driver_t* p); -#endif - - -struct aubio_mdriver_definition_t aubio_midi_drivers[] = { -#if OSS_SUPPORT - { "oss", - new_aubio_oss_midi_driver, - del_aubio_oss_midi_driver, - aubio_oss_midi_driver_settings }, -#endif -#if ALSA_SUPPORT - { "alsa_raw", - new_aubio_midi_alsa_raw_driver, - del_aubio_midi_alsa_raw_driver, - NULL /*aubio_midi_alsa_raw_driver_settings*/ }, - { "alsa_seq", - new_aubio_alsa_seq_driver, - del_aubio_alsa_seq_driver, - NULL /*aubio_alsa_seq_driver_settings*/ }, -#endif -#if WINMIDI_SUPPORT - { "winmidi", - new_aubio_winmidi_driver, - del_aubio_winmidi_driver, - NULL }, -#endif -#if MIDISHARE_SUPPORT - { "midishare", - new_aubio_midishare_midi_driver, - del_aubio_midishare_midi_driver, - NULL }, -#endif - { NULL, NULL, NULL, NULL } -}; - - -void aubio_midi_driver_settings(aubio_settings_t* settings) -{ - int i; - -#if 0 - /* Set the default driver */ -#if ALSA_SUPPORT - aubio_settings_register_str(settings, "midi.driver", "alsa_seq", 0, NULL, NULL); -#elif OSS_SUPPORT - aubio_settings_register_str(settings, "midi.driver", "oss", 0, NULL, NULL); -#elif WINMIDI_SUPPORT - aubio_settings_register_str(settings, "midi.driver", "winmidi", 0, NULL, NULL); -#elif MIDISHARE_SUPPORT - aubio_settings_register_str(settings, "midi.driver", "midishare", 0, NULL, NULL); -#else - aubio_settings_register_str(settings, "midi.driver", "", 0, NULL, NULL); -#endif - - /* Add all drivers to the list of options */ -#if ALSA_SUPPORT - aubio_settings_add_option(settings, "midi.driver", "alsa_seq"); - aubio_settings_add_option(settings, "midi.driver", "alsa_raw"); -#endif -#if OSS_SUPPORT - aubio_settings_add_option(settings, "midi.driver", "oss"); -#endif -#if WINMIDI_SUPPORT - aubio_settings_add_option(settings, "midi.driver", "winmidi"); -#endif -#if MIDISHARE_SUPPORT - aubio_settings_add_option(settings, "midi.driver", "midishare"); -#endif - -#endif - - for (i = 0; aubio_midi_drivers[i].name != NULL; i++) { - if (aubio_midi_drivers[i].settings != NULL) { - aubio_midi_drivers[i].settings(settings); - } - } -} - -//aubio_midi_driver_t* new_aubio_midi_driver(aubio_settings_t* settings, -aubio_midi_driver_t* new_aubio_midi_driver(char * name, - handle_midi_event_func_t handler, - void* event_handler_data) -{ - int i; - aubio_midi_driver_t* driver = NULL; - for (i = 0; aubio_midi_drivers[i].name != NULL; i++) { - if (AUBIO_STRCMP(name,aubio_midi_drivers[i].name) == 0){ - //if (aubio_settings_str_equal(settings, "midi.driver", aubio_midi_drivers[i].name)) { - AUBIO_DBG( "Using '%s' midi driver\n", aubio_midi_drivers[i].name); - //driver = aubio_midi_drivers[i].new(settings, handler, event_handler_data); - driver = aubio_midi_drivers[i].new(/*name,*/ handler, event_handler_data); - if (driver) { - driver->name = aubio_midi_drivers[i].name; - } - return driver; - } - } - AUBIO_ERR("Couldn't find the requested midi driver"); - return NULL; -} - -void del_aubio_midi_driver(aubio_midi_driver_t* driver) -{ - int i; - - for (i = 0; aubio_midi_drivers[i].name != NULL; i++) { - if (aubio_midi_drivers[i].name == driver->name) { - aubio_midi_drivers[i].free(driver); - return; - } - } -} - diff --git a/src/midi_driver.h b/src/midi_driver.h deleted file mode 100644 index f9a0e7ae..00000000 --- a/src/midi_driver.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License - * as published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - * 02111-1307, USA - */ - -/* this file orginally taken from : - * FluidSynth - A Software Synthesizer - * Copyright (C) 2003 Peter Hanappe and others. - */ - - -/** \file - * generic midi driver - */ - -#ifndef _AUBIO_MDRIVER_H -#define _AUBIO_MDRIVER_H - -typedef void aubio_settings_t; - -typedef int (*handle_midi_event_func_t)(void* data, aubio_midi_event_t* event); - -/** aubio_midi_driver_t */ -typedef struct _aubio_midi_driver_t aubio_midi_driver_t; - -struct _aubio_midi_driver_t -{ - char* name; - handle_midi_event_func_t handler; - void* data; -}; - -//aubio_midi_driver_t* new_aubio_midi_driver(aubio_settings_t* settings, -aubio_midi_driver_t* new_aubio_midi_driver(char * name, - handle_midi_event_func_t handler, - void* event_handler_data); -void del_aubio_midi_driver(aubio_midi_driver_t* driver); -void aubio_midi_driver_settings(aubio_settings_t* settings); - -#include "config.h" -#if JACK_SUPPORT -void aubio_midi_direct_output(aubio_midi_driver_t * dev, aubio_midi_event_t * event); -#endif - -#endif /* _AUBIO_AUDRIVER_H */ diff --git a/src/midi_event.c b/src/midi_event.c deleted file mode 100644 index ae5bb8a1..00000000 --- a/src/midi_event.c +++ /dev/null @@ -1,222 +0,0 @@ -/* - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License - * as published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - * 02111-1307, USA - */ - -/* this file originally taken from FluidSynth - A Software Synthesizer - * Copyright (C) 2003 Peter Hanappe and others. - */ - -#include "aubio_priv.h" -#include "midi_event.h" -#include "midi.h" - -/****************************************************** - * - * aubio_event_t - */ - -/* - * new_aubio_midi_event - */ -aubio_midi_event_t* new_aubio_midi_event() -{ - aubio_midi_event_t* evt; - evt = AUBIO_NEW(aubio_midi_event_t); - if (evt == NULL) { - AUBIO_ERR( "Out of memory"); - return NULL; - } - evt->dtime = 0; - evt->type = 0; - evt->channel = 0; - evt->param1 = 0; - evt->param2 = 0; - evt->next = NULL; - return evt; -} - -/** del_aubio_midi_event */ -int del_aubio_midi_event(aubio_midi_event_t* evt) -{ - aubio_midi_event_t *temp; - while(evt) - { - temp = evt->next; - AUBIO_FREE(evt); - evt = temp; - } - return AUBIO_OK; -} - -/* - * aubio_midi_event_get_type - */ -int aubio_midi_event_get_type(aubio_midi_event_t* evt) -{ - return evt->type; -} - -/* - * aubio_midi_event_set_type - */ -int aubio_midi_event_set_type(aubio_midi_event_t* evt, int type) -{ - evt->type = type; - return AUBIO_OK; -} - -/* - * aubio_midi_event_get_channel - */ -int aubio_midi_event_get_channel(aubio_midi_event_t* evt) -{ - return evt->channel; -} - -/* - * aubio_midi_event_set_channel - */ -int aubio_midi_event_set_channel(aubio_midi_event_t* evt, int chan) -{ - evt->channel = chan; - return AUBIO_OK; -} - -/* - * aubio_midi_event_get_key - */ -int aubio_midi_event_get_key(aubio_midi_event_t* evt) -{ - return evt->param1; -} - -/* - * aubio_midi_event_set_key - */ -int aubio_midi_event_set_key(aubio_midi_event_t* evt, int v) -{ - evt->param1 = v; - return AUBIO_OK; -} - -/* - * aubio_midi_event_get_velocity - */ -int aubio_midi_event_get_velocity(aubio_midi_event_t* evt) -{ - return evt->param2; -} - -/* - * aubio_midi_event_set_velocity - */ -int aubio_midi_event_set_velocity(aubio_midi_event_t* evt, int v) -{ - evt->param2 = v; - return AUBIO_OK; -} - -/* - * aubio_midi_event_get_control - */ -int aubio_midi_event_get_control(aubio_midi_event_t* evt) -{ - return evt->param1; -} - -/* - * aubio_midi_event_set_control - */ -int aubio_midi_event_set_control(aubio_midi_event_t* evt, int v) -{ - evt->param1 = v; - return AUBIO_OK; -} - -/* - * aubio_midi_event_get_value - */ -int aubio_midi_event_get_value(aubio_midi_event_t* evt) -{ - return evt->param2; -} - -/* - * aubio_midi_event_set_value - */ -int aubio_midi_event_set_value(aubio_midi_event_t* evt, int v) -{ - evt->param2 = v; - return AUBIO_OK; -} - -int aubio_midi_event_get_program(aubio_midi_event_t* evt) -{ - return evt->param1; -} - -int aubio_midi_event_set_program(aubio_midi_event_t* evt, int val) -{ - evt->param1 = val; - return AUBIO_OK; -} - -int aubio_midi_event_get_pitch(aubio_midi_event_t* evt) -{ - return evt->param1; -} - -int aubio_midi_event_set_pitch(aubio_midi_event_t* evt, int val) -{ - evt->param1 = val; - return AUBIO_OK; -} - -/* - * aubio_midi_event_get_param1 - */ -/* int aubio_midi_event_get_param1(aubio_midi_event_t* evt) */ -/* { */ -/* return evt->param1; */ -/* } */ - -/* - * aubio_midi_event_set_param1 - */ -/* int aubio_midi_event_set_param1(aubio_midi_event_t* evt, int v) */ -/* { */ -/* evt->param1 = v; */ -/* return AUBIO_OK; */ -/* } */ - -/* - * aubio_midi_event_get_param2 - */ -/* int aubio_midi_event_get_param2(aubio_midi_event_t* evt) */ -/* { */ -/* return evt->param2; */ -/* } */ - -/* - * aubio_midi_event_set_param2 - */ -/* int aubio_midi_event_set_param2(aubio_midi_event_t* evt, int v) */ -/* { */ -/* evt->param2 = v; */ -/* return AUBIO_OK; */ -/* } */ - diff --git a/src/midi_event.h b/src/midi_event.h deleted file mode 100644 index 4a9bbe4d..00000000 --- a/src/midi_event.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License - * as published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - * 02111-1307, USA - */ - -/* this file originally taken from FluidSynth - A Software Synthesizer - * Copyright (C) 2003 Peter Hanappe and others. - */ - -/** \file - * midi event structure - */ - -#ifndef _AUBIO_MIDI_EVENT_H -#define _AUBIO_MIDI_EVENT_H - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct _aubio_midi_event_t aubio_midi_event_t; - -/* - * aubio_midi_event_t - */ -struct _aubio_midi_event_t { - aubio_midi_event_t* next; /**< Don't use it, it will dissappear. Used in midi tracks. */ - unsigned int dtime; /**< Delay (ticks) between this and previous event. midi tracks. */ - unsigned char type; /**< MIDI event type */ - unsigned char channel; /**< MIDI channel */ - unsigned int param1; /**< First parameter */ - unsigned int param2; /**< Second parameter */ -}; - -aubio_midi_event_t* new_aubio_midi_event(void); -int del_aubio_midi_event(aubio_midi_event_t* event); -int aubio_midi_event_set_type(aubio_midi_event_t* evt, int type); -int aubio_midi_event_get_type(aubio_midi_event_t* evt); -int aubio_midi_event_set_channel(aubio_midi_event_t* evt, int chan); -int aubio_midi_event_get_channel(aubio_midi_event_t* evt); -int aubio_midi_event_get_key(aubio_midi_event_t* evt); -int aubio_midi_event_set_key(aubio_midi_event_t* evt, int key); -int aubio_midi_event_get_velocity(aubio_midi_event_t* evt); -int aubio_midi_event_set_velocity(aubio_midi_event_t* evt, int vel); -int aubio_midi_event_get_control(aubio_midi_event_t* evt); -int aubio_midi_event_set_control(aubio_midi_event_t* evt, int ctrl); -int aubio_midi_event_get_value(aubio_midi_event_t* evt); -int aubio_midi_event_set_value(aubio_midi_event_t* evt, int val); -int aubio_midi_event_get_program(aubio_midi_event_t* evt); -int aubio_midi_event_set_program(aubio_midi_event_t* evt, int val); -int aubio_midi_event_get_pitch(aubio_midi_event_t* evt); -int aubio_midi_event_set_pitch(aubio_midi_event_t* evt, int val); -int aubio_midi_event_length(unsigned char status); - -#ifdef __cplusplus -} -#endif - -#endif/*_AUBIO_MIDI_EVENT_H*/ diff --git a/src/midi_file.c b/src/midi_file.c deleted file mode 100644 index c069a78e..00000000 --- a/src/midi_file.c +++ /dev/null @@ -1,633 +0,0 @@ -/* - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License - * as published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - * 02111-1307, USA - */ - -/* this file originally taken from FluidSynth - A Software Synthesizer - * Copyright (C) 2003 Peter Hanappe and others. - * - * \note fixed some track names causing segfault - */ - -#include "aubio_priv.h" -#include "midi.h" -#include "midi_event.h" -#include "midi_track.h" -#include "midi_player.h" -#include "midi_file.h" - - -/** aubio_midi_file */ -struct _aubio_midi_file_t{ - //aubio_file_t fp; - FILE *fp; - int running_status; - int c; - int type; - int ntracks; - int uses_smpte; - unsigned int smpte_fps; - unsigned int smpte_res; - unsigned int division; /* If uses_SMPTE == 0 then division is - ticks per beat (quarter-note) */ - double tempo; /* Beats per second (SI rules =) */ - int tracklen; - int trackpos; - int eot; - int varlen; -}; - -/*************************************************************** - * - * MIDIFILE - */ - -/** new_aubio_midi_file */ -aubio_midi_file_t * new_aubio_midi_file(char* filename) -{ - aubio_midi_file_t* mf; - - mf = AUBIO_NEW(aubio_midi_file_t); - if (mf == NULL) { - AUBIO_ERR( "Out of memory"); - return NULL; - } - AUBIO_MEMSET(mf, 0, sizeof(aubio_midi_file_t)); - - mf->c = -1; - mf->running_status = -1; - mf->fp = AUBIO_FOPEN(filename, "rb"); - - if (mf->fp == NULL) { - AUBIO_ERR( "Couldn't open the MIDI file !\n"); - AUBIO_FREE(mf); - return NULL; - } - - if (aubio_midi_file_read_mthd(mf) != AUBIO_OK) { - AUBIO_FREE(mf); - return NULL; - } - return mf; -} - -/** del_aubio_midi_file */ -void del_aubio_midi_file(aubio_midi_file_t* mf) -{ - if (mf == NULL) { - return; - } - if (mf->fp != NULL) { - AUBIO_FCLOSE(mf->fp); - } - AUBIO_FREE(mf); - return; -} - -/** aubio_midi_file_getc */ -int aubio_midi_file_getc(aubio_midi_file_t* mf) -{ - unsigned char c; - int n; - if (mf->c >= 0) { - c = mf->c; - mf->c = -1; - } else { - n = AUBIO_FREAD(&c, 1, 1, mf->fp); - mf->trackpos++; - } - return (int) c; -} - -/** aubio_midi_file_push */ -int aubio_midi_file_push(aubio_midi_file_t* mf, int c) -{ - mf->c = c; - return AUBIO_OK; -} - -/** aubio_midi_file_read */ -int aubio_midi_file_read(aubio_midi_file_t* mf, void* buf, int len) -{ - int num = AUBIO_FREAD(buf, 1, len, mf->fp); - mf->trackpos += num; -#if DEBUG - if (num != len) { - AUBIO_DBG( "Coulnd't read the requested number of bytes"); - } -#endif - return (num != len)? AUBIO_FAIL : AUBIO_OK; -} - -/** aubio_midi_file_skip */ -int aubio_midi_file_skip(aubio_midi_file_t* mf, int skip) -{ - int err = AUBIO_FSEEK(mf->fp, skip, SEEK_CUR); - if (err) { - AUBIO_ERR( "FAIL to seek position in file"); - return AUBIO_FAIL; - } - return AUBIO_OK; -} - -/** aubio_midi_file_read_mthd */ -int aubio_midi_file_read_mthd(aubio_midi_file_t* mf) -{ - char mthd[15]; - if (aubio_midi_file_read(mf, mthd, 14) != AUBIO_OK) { - return AUBIO_FAIL; - } - if ((AUBIO_STRNCMP(mthd, "MThd", 4) != 0) || (mthd[7] != 6) || (mthd[9] > 2)) { - AUBIO_ERR( "Doesn't look like a MIDI file: invalid MThd header"); - return AUBIO_FAIL; - } - mf->type = mthd[9]; - mf->ntracks = (unsigned) mthd[11]; - mf->ntracks += (unsigned int) (mthd[10]) << 16; - /** \bug: smpte timing not yet implemented */ - if((int)(mthd[12]) < 0){ - /*if((mthd[12]) < 0){*/ - mf->uses_smpte = 1; - mf->smpte_fps = -mthd[12]; - mf->smpte_res = (unsigned) mthd[13]; - AUBIO_ERR( "File uses SMPTE timing -- Not implemented yet"); - return AUBIO_FAIL; - } else { - mf->uses_smpte = 0; - mf->division = (mthd[12] << 8) | (mthd[13] & 0xff); - } - return AUBIO_OK; -} - -/** aubio_midi_file_load_tracks */ -int aubio_midi_file_load_tracks(aubio_midi_file_t* mf, aubio_midi_player_t* player) -{ - int i; - for (i = 0; i < mf->ntracks; i++) { - if (aubio_midi_file_read_track(mf, player, i) != AUBIO_OK) { - return AUBIO_FAIL; - } - } - return AUBIO_OK; -} - -/** aubio_midi_file_read_tracklen */ -int aubio_midi_file_read_tracklen(aubio_midi_file_t* mf) -{ - unsigned char length[5]; - if (aubio_midi_file_read(mf, length, 4) != AUBIO_OK) { - return AUBIO_FAIL; - } - mf->tracklen = aubio_getlength(length); - mf->trackpos = 0; - mf->eot = 0; - return AUBIO_OK; -} - -/** aubio_midi_file_eot */ -int aubio_midi_file_eot(aubio_midi_file_t* mf) -{ -#if DEBUG - if (mf->trackpos > mf->tracklen) { - printf("track overrun: %d > %d\n", mf->trackpos, mf->tracklen); - } -#endif - return mf->eot || (mf->trackpos >= mf->tracklen); -} - -/** aubio_midi_file_read_track */ -int aubio_midi_file_read_track(aubio_midi_file_t* mf, aubio_midi_player_t* player, int num) -{ - aubio_track_t* track; - unsigned char id[5], length[5]; - int found_track = 0; - int skip; - - AUBIO_DBG("Loading track %d\n",num); - if (aubio_midi_file_read(mf, id, 4) != AUBIO_OK) { - AUBIO_DBG("Failed loading track %d\n",num); - return AUBIO_FAIL; - } - - id[4]='\0'; - - while (!found_track){ - - if (aubio_isasciistring((char*) id) == 0) { - AUBIO_ERR( "An non-ascii track header found, currupt file"); - return AUBIO_FAIL; - - } else if (strcmp((char*) id, "MTrk") == 0) { - - found_track = 1; - - if (aubio_midi_file_read_tracklen(mf) != AUBIO_OK) { - return AUBIO_FAIL; - } - - track = new_aubio_track(num); - if (track == NULL) { - AUBIO_ERR( "Out of memory"); - return AUBIO_FAIL; - } - - while (!aubio_midi_file_eot(mf)) { - if (aubio_midi_file_read_event(mf, track) != AUBIO_OK) { - return AUBIO_FAIL; - } - } - - aubio_midi_player_add_track(player, track); - } else { - found_track = 0; - if (aubio_midi_file_read(mf, length, 4) != AUBIO_OK) { - return AUBIO_FAIL; - } - skip = aubio_getlength(length); - /* fseek(mf->fp, skip, SEEK_CUR); */ - if (aubio_midi_file_skip(mf, skip) != AUBIO_OK) { - return AUBIO_FAIL; - } - } - } - - if (feof(mf->fp)) { - AUBIO_ERR( "Unexpected end of file"); - return AUBIO_FAIL; - } - AUBIO_DBG("Loaded track %d\n",num); - return AUBIO_OK; -} - -/** aubio_midi_file_read_varlen */ -int aubio_midi_file_read_varlen(aubio_midi_file_t* mf) -{ - int i; - int c; - mf->varlen = 0; - for (i = 0;;i++) { - if (i == 4) { - AUBIO_ERR( "Invalid variable length number"); - return AUBIO_FAIL; - } - c = aubio_midi_file_getc(mf); - if (c < 0) { - AUBIO_ERR( "Unexpected end of file"); - return AUBIO_FAIL; - } - if (c & 0x80){ - mf->varlen |= (int) (c & 0x7F); - mf->varlen <<= 7; - } else { - mf->varlen += c; - break; - } - } - return AUBIO_OK; -} - -/** aubio_midi_file_read_event */ -int aubio_midi_file_read_event(aubio_midi_file_t* mf, aubio_track_t* track) -{ - int dtime; - int status; - int type; - int tempo; - unsigned char* metadata = NULL; - unsigned char* dyn_buf = NULL; - unsigned char static_buf[256]; - int nominator, denominator, clocks, notes, sf, mi; - aubio_midi_event_t* evt; - int channel = 0; - int param1 = 0; - int param2 = 0; - - - /* read the delta-time of the event */ - if (aubio_midi_file_read_varlen(mf) != AUBIO_OK) { - return AUBIO_FAIL; - } - dtime = mf->varlen; - - /* read the status byte */ - status = aubio_midi_file_getc(mf); - if (status < 0) { - AUBIO_ERR( "Unexpected end of file"); - return AUBIO_FAIL; - } - - /* not a valid status byte: use the running status instead */ - if ((status & 0x80) == 0) { - if ((mf->running_status & 0x80) == 0) { - AUBIO_ERR( "Undefined status and invalid running status"); - return AUBIO_FAIL; - } - aubio_midi_file_push(mf, status); - status = mf->running_status; - } - - /* check what message we have */ - if (status & 0x80) { - mf->running_status = status; - - if ((status == MIDI_SYSEX) || (status == MIDI_EOX)) { /* system exclusif */ - /** \bug Sysex messages are not handled yet */ - /* read the length of the message */ - if (aubio_midi_file_read_varlen(mf) != AUBIO_OK) { - return AUBIO_FAIL; - } - - if (mf->varlen < 255) { - metadata = &static_buf[0]; - } else { - AUBIO_DBG( "%s: %d: alloc metadata, len = %d", __FILE__, __LINE__, mf->varlen); - dyn_buf = AUBIO_MALLOC(mf->varlen + 1); - if (dyn_buf == NULL) { - //AUBIO_LOG(AUBIO_PANIC, "Out of memory"); - AUBIO_ERR("Out of memory"); - return AUBIO_FAIL; - } - metadata = dyn_buf; - } - - /* read the data of the message */ - if (mf->varlen) { - - if (aubio_midi_file_read(mf, metadata, mf->varlen) != AUBIO_OK) { - if (dyn_buf) { - AUBIO_FREE(dyn_buf); - } - return AUBIO_FAIL; - } - - if (dyn_buf) { - AUBIO_DBG( "%s: %d: free metadata", __FILE__, __LINE__); - AUBIO_FREE(dyn_buf); - } - } - - return AUBIO_OK; - - } else if (status == MIDI_META_EVENT) { /* meta events */ - - int result = AUBIO_OK; - - /* get the type of the meta message */ - type = aubio_midi_file_getc(mf); - if (type < 0) { - AUBIO_ERR( "Unexpected end of file"); - return AUBIO_FAIL; - } - - /* get the length of the data part */ - if (aubio_midi_file_read_varlen(mf) != AUBIO_OK) { - return AUBIO_FAIL; - } - - if (mf->varlen) { - - if (mf->varlen < 255) { - metadata = &static_buf[0]; - } else { - AUBIO_DBG( "%s: %d: alloc metadata, len = %d", __FILE__, __LINE__, mf->varlen); - dyn_buf = AUBIO_MALLOC(mf->varlen + 1); - if (dyn_buf == NULL) { - AUBIO_ERR("Out of memory"); - return AUBIO_FAIL; - } - metadata = dyn_buf; - } - - /* read the data */ - if (aubio_midi_file_read(mf, metadata, mf->varlen) != AUBIO_OK) { - if (dyn_buf) { - AUBIO_FREE(dyn_buf); - } - return AUBIO_FAIL; - } - } - - /* handle meta data */ - switch (type) { - - case MIDI_COPYRIGHT: - metadata[mf->varlen] = 0; - break; - - case MIDI_TRACK_NAME: - if (metadata != NULL) /* avoids crashes on empty tracks */ - metadata[mf->varlen] = 0; - aubio_track_set_name(track, (char*) metadata); - break; - - case MIDI_INST_NAME: - metadata[mf->varlen] = 0; - break; - - case MIDI_LYRIC: - break; - - case MIDI_MARKER: - break; - - case MIDI_CUE_POINT: - break; /* don't care much for text events */ - - case MIDI_EOT: - if (mf->varlen != 0) { - AUBIO_ERR("Invalid length for EndOfTrack event"); - result = AUBIO_FAIL; - break; - } - mf->eot = 1; - break; - - case MIDI_SET_TEMPO: - if (mf->varlen != 3) { - AUBIO_ERR("Invalid length for SetTempo meta event"); - result = AUBIO_FAIL; - break; - } - tempo = (metadata[0] << 16) + (metadata[1] << 8) + metadata[2]; - evt = new_aubio_midi_event(); - if (evt == NULL) { - AUBIO_ERR( "Out of memory"); - result = AUBIO_FAIL; - break; - } - evt->dtime = dtime; - evt->type = MIDI_SET_TEMPO; - evt->channel = 0; - evt->param1 = tempo; - evt->param2 = 0; - aubio_track_add_event(track, evt); - break; - - case MIDI_SMPTE_OFFSET: - if (mf->varlen != 5) { - AUBIO_ERR("Invalid length for SMPTE Offset meta event"); - result = AUBIO_FAIL; - break; - } - break; /* we don't use smtp */ - - case MIDI_TIME_SIGNATURE: - if (mf->varlen != 4) { - AUBIO_ERR("Invalid length for TimeSignature meta event"); - result = AUBIO_FAIL; - break; - } - nominator = metadata[0]; - denominator = pow(2.0, (double) metadata[1]); - clocks = metadata[2]; - notes = metadata[3]; - - AUBIO_DBG("signature=%d/%d, metronome=%d, 32nd-notes=%d\n", - nominator, denominator, clocks, notes); - - break; - - case MIDI_KEY_SIGNATURE: - if (mf->varlen != 2) { - AUBIO_ERR( "Invalid length for KeySignature meta event"); - result = AUBIO_FAIL; - break; - } - sf = metadata[0]; - mi = metadata[1]; - break; - - case MIDI_SEQUENCER_EVENT: - AUBIO_DBG("Sequencer event ignored\n"); - break; - - default: - break; - } - - if (dyn_buf) { - AUBIO_DBG( "%s: %d: free metadata", __FILE__, __LINE__); - AUBIO_FREE(dyn_buf); - } - - return result; - - } else { /* channel messages */ - - type = status & 0xf0; - channel = status & 0x0f; - - /* all channel message have at least 1 byte of associated data */ - if ((param1 = aubio_midi_file_getc(mf)) < 0) { - AUBIO_ERR( "Unexpected end of file"); - return AUBIO_FAIL; - } - - switch (type) { - - case NOTE_ON: - if ((param2 = aubio_midi_file_getc(mf)) < 0) { - AUBIO_ERR( "Unexpected end of file"); - return AUBIO_FAIL; - } - break; - - case NOTE_OFF: - if ((param2 = aubio_midi_file_getc(mf)) < 0) { - AUBIO_ERR( "Unexpected end of file"); - return AUBIO_FAIL; - } - break; - - case KEY_PRESSURE: - if ((param2 = aubio_midi_file_getc(mf)) < 0) { - AUBIO_ERR( "Unexpected end of file"); - return AUBIO_FAIL; - } - break; - - case CONTROL_CHANGE: - if ((param2 = aubio_midi_file_getc(mf)) < 0) { - AUBIO_ERR( "Unexpected end of file"); - return AUBIO_FAIL; - } - break; - - case PROGRAM_CHANGE: - break; - - case CHANNEL_PRESSURE: - break; - - case PITCH_BEND: - if ((param2 = aubio_midi_file_getc(mf)) < 0) { - AUBIO_ERR( "Unexpected end of file"); - return AUBIO_FAIL; - } - - param1 = ((param2 & 0x7f) << 7) | (param1 & 0x7f); - param2 = 0; - break; - - default: - /* Can't possibly happen !? */ - AUBIO_ERR( "Unrecognized MIDI event"); - return AUBIO_FAIL; - } - evt = new_aubio_midi_event(); - if (evt == NULL) { - AUBIO_ERR( "Out of memory"); - return AUBIO_FAIL; - } - evt->dtime = dtime; - evt->type = type; - evt->channel = channel; - evt->param1 = param1; - evt->param2 = param2; - aubio_track_add_event(track, evt); - } - } - return AUBIO_OK; -} - -/** aubio_midi_file_get_division */ -int aubio_midi_file_get_division(aubio_midi_file_t* midifile) -{ - return midifile->division; -} - - -/** aubio_isasciistring */ -int aubio_isasciistring(char* s) -{ - int i; - int len = (int) AUBIO_STRLEN(s); - for (i = 0; i < len; i++) { - if (!aubio_isascii(s[i])) { - return 0; - } - } - return 1; -} - -/** aubio_getlength */ -long aubio_getlength(unsigned char *s) -{ - long i = 0; - i = s[3] | (s[2]<<8) | (s[1]<<16) | (s[0]<<24); - return i; -} - diff --git a/src/midi_file.h b/src/midi_file.h deleted file mode 100644 index 9c9fb0da..00000000 --- a/src/midi_file.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License - * as published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - * 02111-1307, USA - */ - -/* this file originally taken from FluidSynth - A Software Synthesizer - * Copyright (C) 2003 Peter Hanappe and others. - */ - -/** \file - * midi file reader - */ - -#ifndef _AUBIO_MIDI_FILE_H -#define _AUBIO_MIDI_FILE_H - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct _aubio_midi_file_t aubio_midi_file_t; - - -aubio_midi_file_t* new_aubio_midi_file(char* filename); -void del_aubio_midi_file(aubio_midi_file_t* mf); -int aubio_midi_file_read_mthd(aubio_midi_file_t* midifile); -int aubio_midi_file_load_tracks(aubio_midi_file_t* midifile, aubio_midi_player_t* player); -int aubio_midi_file_read_track(aubio_midi_file_t* mf, aubio_midi_player_t* player, int num); -int aubio_midi_file_read_event(aubio_midi_file_t* mf, aubio_track_t* track); -int aubio_midi_file_read_varlen(aubio_midi_file_t* mf); -int aubio_midi_file_getc(aubio_midi_file_t* mf); -int aubio_midi_file_push(aubio_midi_file_t* mf, int c); -int aubio_midi_file_read(aubio_midi_file_t* mf, void* buf, int len); -int aubio_midi_file_skip(aubio_midi_file_t* mf, int len); -int aubio_midi_file_read_tracklen(aubio_midi_file_t* mf); -int aubio_midi_file_eot(aubio_midi_file_t* mf); -int aubio_midi_file_get_division(aubio_midi_file_t* midifile); - - -/* From ctype.h */ -#define aubio_isascii(c) (((c) & ~0x7f) == 0) -int aubio_isasciistring(char* s); -long aubio_getlength(unsigned char *s); - -#ifdef __cplusplus -} -#endif - -#endif /*_AUBIO_MIDI_FILE_H*/ diff --git a/src/midi_parser.c b/src/midi_parser.c deleted file mode 100644 index ed47935a..00000000 --- a/src/midi_parser.c +++ /dev/null @@ -1,221 +0,0 @@ -/* - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License - * as published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - * 02111-1307, USA - */ - -/* This file orginally taken from, Fluidsynth, Peter Hanappe */ - -#include "aubio_priv.h" -#include "midi.h" -#include "midi_event.h" -#include "midi_parser.h" - -/** aubio_midi_parser_t */ -struct _aubio_midi_parser_t { - unsigned char status; /**< Identifies the type of event, that is - currently received ('Noteon', 'Pitch Bend' - etc). */ - unsigned char channel; /**< The channel of the event that is received - (in case of a channel event) */ - unsigned int nr_bytes; /**< How many bytes have been read for the - current event? */ - unsigned int nr_bytes_total;/**< How many bytes does the current event - type include? */ - unsigned short p[AUBIO_MIDI_PARSER_MAX_PAR]; /**< The parameters */ - - aubio_midi_event_t event; /**< The event, that is returned to the - MIDI driver. */ -}; - -/** new_aubio_midi_parser */ -aubio_midi_parser_t* new_aubio_midi_parser() -{ - aubio_midi_parser_t* parser; - parser = AUBIO_NEW(aubio_midi_parser_t); - if (parser == NULL) { - AUBIO_ERR("Out of memory"); - return NULL; - } - /* As long as the status is 0, the parser won't do anything -> no need to - * initialize all the fields. */ - parser->status = 0; - return parser; -} - -/** del_aubio_midi_parser */ -int del_aubio_midi_parser(aubio_midi_parser_t* parser) -{ - AUBIO_FREE(parser); - return AUBIO_OK; -} - -/** aubio_midi_parser_parse - * - * The MIDI byte stream is fed into the parser, one byte at a time. - * As soon as the parser has recognized an event, it will return it. - * Otherwise it returns NULL. - */ -aubio_midi_event_t* aubio_midi_parser_parse(aubio_midi_parser_t* parser, - unsigned char c) -{ - /*********************************************************************/ - /* 'Process' system real-time messages */ - /*********************************************************************/ - /* There are not too many real-time messages that are of interest here. - * They can occur anywhere, even in the middle of a noteon message! - * Real-time range: 0xF8 .. 0xFF - * Note: Real-time does not affect (running) status. - */ - if (c >= 0xF8){ - if (c == MIDI_SYSTEM_RESET){ - parser->event.type = c; - parser->status = 0; /* clear the status */ - return &parser->event; - }; - return NULL; - }; - - /*********************************************************************/ - /* 'Process' system common messages (again, just skip them) */ - /*********************************************************************/ - /* There are no system common messages that are of interest here. - * System common range: 0xF0 .. 0xF7 - */ - - if (c > 0xF0){ - /* MIDI specs say: To ignore a non-real-time message, just discard all data - * up to the next status byte. And our parser will ignore data that is - * received without a valid status. - * Note: system common cancels running status. */ - parser->status = 0; - return NULL; - }; - - /*********************************************************************/ - /* Process voice category messages: */ - /*********************************************************************/ - /* Now that we have handled realtime and system common messages, only - * voice messages are left. - * Only a status byte has bit # 7 set. - * So no matter the status of the parser (in case we have lost sync), - * as soon as a byte >= 0x80 comes in, we are dealing with a status byte - * and start a new event. - */ - - if (c & 0x80){ - parser->channel = c & 0x0F; - parser->status = c & 0xF0; - /* The event consumes x bytes of data... (subtract 1 for the status - * byte) */ - parser->nr_bytes_total=aubio_midi_event_length(parser->status)-1; - /* of which we have read 0 at this time. */ - parser->nr_bytes = 0; - return NULL; - }; - - /*********************************************************************/ - /* Process data */ - /*********************************************************************/ - /* If we made it this far, then the received char belongs to the data - * of the last event. */ - if (parser->status == 0){ - /* We are not interested in the event currently received. - * Discard the data. */ - return NULL; - }; - - /* Store the first couple of bytes */ - if (parser->nr_bytes < AUBIO_MIDI_PARSER_MAX_PAR){ - parser->p[parser->nr_bytes]=c; - }; - parser->nr_bytes++; - - /* Do we still need more data to get this event complete? */ - if (parser->nr_bytes < parser->nr_bytes_total){ - return NULL; - }; - - /*********************************************************************/ - /* Send the event */ - /*********************************************************************/ - /* The event is ready-to-go. About 'running status': - * - * The MIDI protocol has a built-in compression mechanism. If several similar - * events are sent in-a-row, for example note-ons, then the event type is - * only sent once. For this case, the last event type (status) is remembered. - * We simply keep the status as it is, just reset the parameter counter. If - * another status byte comes in, it will overwrite the status. - */ - parser->event.type = parser->status; - parser->event.channel = parser->channel; - parser->nr_bytes = 0; /* Related to running status! */ - switch (parser->status){ - case NOTE_OFF: - case NOTE_ON: - case KEY_PRESSURE: - case CONTROL_CHANGE: - case PROGRAM_CHANGE: - case CHANNEL_PRESSURE: - parser->event.param1 = parser->p[0]; /* For example key number */ - parser->event.param2 = parser->p[1]; /* For example velocity */ - break; - case PITCH_BEND: - /* Pitch-bend is transmitted with 14-bit precision. */ - /* Note: '|' does here the same as '+' (no common bits), - * but might be faster */ - parser->event.param1 = ((parser->p[1] << 7) | parser->p[0]); - break; - default: - /* Unlikely */ - return NULL; - }; - return &parser->event; -}; - - - -/* Taken from Nagano Daisuke's USB-MIDI driver */ -static int remains_f0f6[] = { - 0, /* 0xF0 */ - 2, /* 0XF1 */ - 3, /* 0XF2 */ - 2, /* 0XF3 */ - 2, /* 0XF4 (Undefined by MIDI Spec, and subject to change) */ - 2, /* 0XF5 (Undefined by MIDI Spec, and subject to change) */ - 1 /* 0XF6 */ -}; - -static int remains_80e0[] = { - 3, /* 0x8X Note Off */ - 3, /* 0x9X Note On */ - 3, /* 0xAX Poly-key pressure */ - 3, /* 0xBX Control Change */ - 2, /* 0xCX Program Change */ - 2, /* 0xDX Channel pressure */ - 3 /* 0xEX PitchBend Change */ -}; - -/** Returns the length of the MIDI message starting with c. - * - * Taken from Nagano Daisuke's USB-MIDI driver */ -int aubio_midi_event_length(unsigned char event){ - if ( event < 0xf0 ) { - return remains_80e0[((event-0x80)>>4)&0x0f]; - } else if ( event < 0xf7 ) { - return remains_f0f6[event-0xf0]; - } else { - return 1; - } -} diff --git a/src/midi_parser.h b/src/midi_parser.h deleted file mode 100644 index 6fa25df1..00000000 --- a/src/midi_parser.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License - * as published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - * 02111-1307, USA - */ - -/* this file originally taken from FluidSynth - A Software Synthesizer - * Copyright (C) 2003 Peter Hanappe and others. - */ - - -/** \file - * midi parser - */ - -#ifndef _AUBIO_MIDI_PARSER_H -#define _AUBIO_MIDI_PARSER_H - - -#ifdef __cplusplus -extern "C" { -#endif - -/* How many parameters may a MIDI event have? */ -#define AUBIO_MIDI_PARSER_MAX_PAR 3 - -typedef struct _aubio_midi_parser_t aubio_midi_parser_t; - -aubio_midi_parser_t* new_aubio_midi_parser(void); -int del_aubio_midi_parser(aubio_midi_parser_t* parser); -aubio_midi_event_t* aubio_midi_parser_parse(aubio_midi_parser_t* parser, unsigned char c); - -#ifdef __cplusplus -} -#endif - -#endif /*_AUBIO_MIDI_PARSER_H*/ diff --git a/src/midi_player.c b/src/midi_player.c deleted file mode 100644 index 94854429..00000000 --- a/src/midi_player.c +++ /dev/null @@ -1,492 +0,0 @@ -/* - * Copyright (C) 2003 Peter Hanappe and others. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License - * as published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - * 02111-1307, USA - */ - -/* this file originally taken from FluidSynth - A Software Synthesizer - * modified by Paul Brossier for aubio - */ - -/** - * - * \bug timer still broken - * (should use alsa seq anyway) (fixed?) realtime playing is slower than - * it should. moved msec_passed and deltatime to microseconds (usec) - * (rounding were causing the drift) the new offline version is not quite - * exact yet. - * - * \bug the player does not seem to understand a ``reprise'' in a file - */ - -#include "aubio_priv.h" -#include "list.h" -#include "timer.h" -#include "midi.h" -#include "midi_event.h" -#include "midi_track.h" -#include "midi_player.h" -#include "midi_file.h" - - -/** aubio_midi_player */ -struct _aubio_midi_player_t { - aubio_track_t *track[AUBIO_MIDI_PLAYER_MAX_TRACKS]; - aubio_timer_t* timer; - sint_t status; - sint_t loop; - sint_t ntracks; - aubio_list_t* playlist; - char* current_file; - char send_program_change;/**< should we ignore the program changes? */ - sint_t ticks_passed; /**< number of midi ticks that have passed */ - sint_t usec_passed; /**< number of microseconds that have passed */ - sint_t miditempo; /**< as indicated by midi settempo: n 24th of a - * usec per midi-clock. bravo! */ - lsmp_t deltatime; /**< microseconds per midi tick. depends on - * set-tempo */ - uint_t division; /**< the number of ticks per beat (quarter-note) - * in the file*/ - //aubio_synth_t* synth; -}; - -/****************************************************** - * - * aubio_midi_player - */ -/** new_aubio_midi_player */ -aubio_midi_player_t* new_aubio_midi_player() - //aubio_midi_player_t* new_aubio_midi_player(aubio_synth_t* synth) -{ - sint_t i; - aubio_midi_player_t* player; - player = AUBIO_NEW(aubio_midi_player_t); - if (player == NULL) { - AUBIO_ERR( "Out of memory"); - return NULL; - } - player->status = AUBIO_MIDI_PLAYER_READY; - player->loop = 0; - player->ntracks = 0; - for (i = 0; i < AUBIO_MIDI_PLAYER_MAX_TRACKS; i++) { - player->track[i] = NULL; - } - //player->synth = synth; - player->timer = NULL; - player->playlist = NULL; - player->current_file = NULL; - player->division = 0; - player->send_program_change = 1; - player->ticks_passed = 0; - player->usec_passed = 0; - player->miditempo = 480000; - player->deltatime = 4000.0; - return player; -} - -/** delete_aubio_midi_player */ -sint_t del_aubio_midi_player(aubio_midi_player_t* player) -{ - if (player == NULL) { - return AUBIO_OK; - } - aubio_midi_player_stop(player); - aubio_midi_player_reset(player); - AUBIO_FREE(player); - return AUBIO_OK; -} - -/** aubio_midi_player_reset */ -sint_t aubio_midi_player_reset(aubio_midi_player_t* player) -{ - sint_t i; - - for (i = 0; i < AUBIO_MIDI_PLAYER_MAX_TRACKS; i++) { - if (player->track[i] != NULL) { - del_aubio_track(player->track[i]); - player->track[i] = NULL; - } - } - player->current_file = NULL; - player->status = AUBIO_MIDI_PLAYER_READY; - player->loop = 0; - player->ntracks = 0; - player->division = 0; - player->send_program_change = 1; - player->ticks_passed = 0; - player->usec_passed = 0; - player->miditempo = 480000; - player->deltatime = 4000.0; - return 0; -} - -/** aubio_midi_player_add_track */ -sint_t aubio_midi_player_add_track(aubio_midi_player_t* player, aubio_track_t* track) -{ - if (player->ntracks < AUBIO_MIDI_PLAYER_MAX_TRACKS) { - player->track[player->ntracks++] = track; - return AUBIO_OK; - } else { - return AUBIO_FAIL; - } -} - -/** aubio_midi_player_count_tracks */ -sint_t aubio_midi_player_count_tracks(aubio_midi_player_t* player) -{ - return player->ntracks; -} - -/** aubio_midi_player_get_track */ -aubio_track_t* aubio_midi_player_get_track(aubio_midi_player_t* player, sint_t i) -{ - if ((i >= 0) && (i < AUBIO_MIDI_PLAYER_MAX_TRACKS)) { - return player->track[i]; - } else { - return NULL; - } -} - -/** aubio_midi_player_get_track */ -sint_t aubio_midi_player_add(aubio_midi_player_t* player, char* midifile) -{ - char *s = AUBIO_STRDUP(midifile); - player->playlist = aubio_list_append(player->playlist, s); - return 0; -} - -/** aubio_midi_player_load */ -sint_t aubio_midi_player_load(aubio_midi_player_t* player, char *filename) -{ - aubio_midi_file_t* midifile; - - midifile = new_aubio_midi_file(filename); - if (midifile == NULL) { - return AUBIO_FAIL; - } - player->division = aubio_midi_file_get_division(midifile); - - AUBIO_DBG("quarter note division=%d\n", player->division); - - if (aubio_midi_file_load_tracks(midifile, player) != AUBIO_OK){ - return AUBIO_FAIL; - } - - AUBIO_DBG("Tracks loaded\n"); - - del_aubio_midi_file(midifile); - return AUBIO_OK; -} - -/** aubio_midi_player_callback */ -sint_t aubio_midi_player_callback(void* data, uint_t usec) -{ - sint_t i; - uint_t ticks; - uint_t delta_ticks; - sint_t status = AUBIO_MIDI_PLAYER_DONE; - aubio_midi_player_t* player; - //aubio_synth_t* synth; - player = (aubio_midi_player_t*) data; - //synth = player->synth; - - /* Load the next file if necessary */ - while (player->current_file == NULL) { - - if (player->playlist == NULL) { - return 0; - } - - aubio_midi_player_reset(player); - - player->current_file = aubio_list_get(player->playlist); - player->playlist = aubio_list_next(player->playlist); - - //AUBIO_DBG( "%s: %d: Loading midifile %s", __FILE__, __LINE__, player->current_file); - AUBIO_DBG("Loading midifile %s\n", player->current_file); - - if (aubio_midi_player_load(player, player->current_file) == AUBIO_OK) { - - player->ticks_passed = 0; - player->usec_passed = 0; - - for (i = 0; i < player->ntracks; i++) { - if (player->track[i] != NULL) { - aubio_track_reset(player->track[i]); - } - } - - } else { - player->current_file = NULL; - } - } - - delta_ticks = (uint_t) ((lsmp_t)(usec - player->usec_passed) / player->deltatime); - ticks = player->ticks_passed + delta_ticks; - - for (i = 0; i < player->ntracks; i++) { - if (!aubio_track_eot(player->track[i])) { - status = AUBIO_MIDI_PLAYER_PLAYING; - if (aubio_track_send_events(player->track[i], /*synth,*/ player, ticks) != AUBIO_OK) { - /* */ - } - } - } - - player->status = status; - player->ticks_passed = ticks; - player->usec_passed = usec; - - if (player->status == AUBIO_MIDI_PLAYER_DONE) { - player->current_file = NULL; - } - - return 1; -} - -/** aubio_midi_player_play */ -sint_t aubio_midi_player_play(aubio_midi_player_t* player) -{ - AUBIO_DBG("Starting midi player\n"); - if (player->status == AUBIO_MIDI_PLAYER_PLAYING) { - AUBIO_DBG("Midi player already playing\n"); - return AUBIO_OK; - } - - if (player->playlist == NULL) { - AUBIO_DBG("No playlist\n"); - return AUBIO_FAIL; - } - - player->status = AUBIO_MIDI_PLAYER_PLAYING; - - /** \bug timer is still in millisec, should be moved to microseconds, - * and replaced in favor of the alsa sequencer api */ - player->timer = new_aubio_timer((sint_t) player->deltatime * 1.e-3, aubio_midi_player_callback, - (void*) player, 1, 0); - if (player->timer == NULL) { - AUBIO_DBG("Failed creating timer for midi player.\n"); - return AUBIO_FAIL; - } - if (player->current_file == NULL) { - AUBIO_DBG("No more file.\n"); - delete_aubio_timer(player->timer); - return AUBIO_FAIL; - } - - return AUBIO_OK; -} - -/** aubio_midi_player_play_offline */ -sint_t aubio_midi_player_play_offline(aubio_midi_player_t* player) -{ - uint_t usec = 0; /* start looking n ms in advance */ - AUBIO_DBG("Starting midi player\n"); - if (player->status == AUBIO_MIDI_PLAYER_PLAYING) { - AUBIO_DBG("Midi player already playing\n"); - return AUBIO_OK; - } - - if (player->playlist == NULL) { - AUBIO_DBG("No playlist\n"); - return AUBIO_FAIL; - } - - //AUBIO_DBG("Starting callback.\n"); - player->status = AUBIO_MIDI_PLAYER_PLAYING; - - /* no timer, no thread ! */ - while(aubio_midi_player_callback((void *)player,usec)) - { - /* step at least one microsecond forward */ - usec += 1 + player->deltatime; - if (player->status == AUBIO_MIDI_PLAYER_DONE) - break; - } - //AUBIO_DBG("End of callback.\n"); - - if (player->current_file == NULL) { - AUBIO_DBG("No more file.\n"); - return AUBIO_FAIL; - } - return AUBIO_OK; -} -/** aubio_midi_player_stop */ -sint_t aubio_midi_player_stop(aubio_midi_player_t* player) -{ - if (player->timer != NULL) { - delete_aubio_timer(player->timer); - } - player->status = AUBIO_MIDI_PLAYER_DONE; - player->timer = NULL; - return AUBIO_OK; -} - -/** aubio_midi_player_set_loop */ -sint_t aubio_midi_player_set_loop(aubio_midi_player_t* player, sint_t loop) -{ - player->loop = loop; - return AUBIO_OK; -} - -/** aubio_midi_player_set_midi_tempo */ -sint_t aubio_midi_player_set_midi_tempo(aubio_midi_player_t* player, sint_t tempo) -{ - player->miditempo = tempo; - //player->deltatime = (lsmp_t) tempo / player->division * 1.e-3; /* in milliseconds */ - player->deltatime = (lsmp_t) tempo / player->division; /* in microseconds */ - - AUBIO_DBG("Tempo Change: %d tempo=%f tick time=%f msec\n", - // player->usec_passed, 60.*1.e6/tempo, player->deltatime); - player->usec_passed, 60.*1.e6/tempo, 1e-3*player->deltatime); - - return AUBIO_OK; -} - -/** aubio_midi_player_set_bpm */ -sint_t aubio_midi_player_set_bpm(aubio_midi_player_t* player, sint_t bpm) -{ - return aubio_midi_player_set_midi_tempo(player, (sint_t)((lsmp_t) 60 * 1e6 / bpm)); -} - -/** aubio_midi_player_join */ -sint_t aubio_midi_player_join(aubio_midi_player_t* player) -{ - return player->timer? aubio_timer_join(player->timer) : AUBIO_OK; -} - -/** aubio_track_send_events */ -sint_t aubio_track_send_events(aubio_track_t* track, - // aubio_synth_t* synth, - aubio_midi_player_t* player, - uint_t ticks) -{ - sint_t status = AUBIO_OK; - aubio_midi_event_t* event; - - while (1) { - - event = track->cur; - if (event == NULL) { - return status; - } - /* prsint_t each midi tick */ - /* - AUBIO_DBG("track=%d\tticks=%u\ttrack=%u\tdtime=%u\tnext=%u\n", - track->num, - ticks, - track->ticks, - event->dtime, - track->ticks + event->dtime); - */ - - if (track->ticks + event->dtime > ticks) { - return status; - } - - track->ticks += event->dtime; - status = aubio_midi_send_event(/*synth, */player, event); - aubio_track_next_event(track); - - } - return status; -} - - -/** - * aubio_midi_send_event - * - * This is a utility function that doesn't really belong to any class or - * structure. It is called by aubio_midi_track and aubio_midi_device. - * - * \note This could be moved to a callback function defined in the main programs - */ -//sint_t aubio_midi_send_event(aubio_synth_t* synth, aubio_player_t* player, aubio_midi_event_t* event) -sint_t aubio_midi_send_event(aubio_midi_player_t* player, aubio_midi_event_t* event) -{ - /* current time in seconds */ - //smpl_t print_time = player->msec_passed * 1e-3; - smpl_t print_time = player->usec_passed * 1e-6; - switch (event->type) { - case NOTE_ON: - AUBIO_MSG("Time=%f, chan=%d, pitch=%d vol=%d \n", - print_time, event->channel, event->param1, event->param2); - /*if (aubio_synth_noteon(synth, event->channel, event->param1, event->param2) != AUBIO_OK) { - return AUBIO_FAIL; - }*/ - break; - case NOTE_OFF: - AUBIO_MSG("Time=%f, chan=%d, pitch=%d, vol=0\n", - print_time, event->channel, event->param1); - /*if (aubio_synth_noteoff(synth, event->channel, event->param1) != AUBIO_OK) { - return AUBIO_FAIL; - }*/ - break; - case CONTROL_CHANGE: - AUBIO_MSG("Time=%f Parameter, chan=%d c1=%d c2=%d\n", - print_time, event->channel, event->param1, event->param2); - /*if (aubio_synth_cc(synth, event->channel, event->param1, event->param2) != AUBIO_OK) { - return AUBIO_FAIL; - }*/ - break; - case MIDI_SET_TEMPO: - if (player != NULL) { - if (aubio_midi_player_set_midi_tempo(player, event->param1) != AUBIO_OK) { - return AUBIO_FAIL; - } - } - break; - case PROGRAM_CHANGE: - AUBIO_MSG("Time=%f Program, chan=%d program=%d\n", - print_time, event->channel, event->param1); - /*if (aubio_synth_program_change(synth, event->channel, event->param1) != AUBIO_OK) { - return AUBIO_FAIL; - }*/ - break; - case PITCH_BEND: - AUBIO_MSG("Time=%f Pitchbend, chan=%d msb=%d lsb=%d \n", - print_time, event->channel, event->param1, event->param2); - /*if (aubio_synth_pitch_bend(synth, event->channel, event->param1) != AUBIO_OK) { - return AUBIO_FAIL; - } - break;*/ - default: - break; - } - return AUBIO_OK; -} - - -/** - * aubio_midi_receive_event - * - * \note This could be moved to a callback function defined in the main programs - */ -sint_t aubio_midi_receive_event(aubio_midi_player_t* player, aubio_midi_event_t* event) -{ - /* current time in seconds */ - //smpl_t print_time = player->msec_passed * 1e-3; - //smpl_t print_time = player->usec_passed * 1e-6; - switch (event->type) { - case NOTE_ON: - break; - case NOTE_OFF: - break; - default: - break; - } - return AUBIO_OK; -} diff --git a/src/midi_player.h b/src/midi_player.h deleted file mode 100644 index b82c3105..00000000 --- a/src/midi_player.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License - * as published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - * 02111-1307, USA - */ - -/* this file originally taken from FluidSynth - A Software Synthesizer - * Copyright (C) 2003 Peter Hanappe and others. - */ - -/** \file - * midi player - */ - - -#ifndef _AUBIO_MIDI_PLAYER_H -#define _AUBIO_MIDI_PLAYER_H - -#define AUBIO_MIDI_PLAYER_MAX_TRACKS 128 - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct _aubio_midi_player_t aubio_midi_player_t; - - -aubio_midi_player_t* new_aubio_midi_player(void); -sint_t del_aubio_midi_player(aubio_midi_player_t* player); -sint_t aubio_midi_player_reset(aubio_midi_player_t* player); -sint_t aubio_midi_player_add_track(aubio_midi_player_t* player, aubio_track_t* track); -sint_t aubio_midi_player_count_tracks(aubio_midi_player_t* player); -aubio_track_t* aubio_midi_player_get_track(aubio_midi_player_t* player, sint_t i); -sint_t aubio_midi_player_add(aubio_midi_player_t* player, char* midifile); -sint_t aubio_midi_player_load(aubio_midi_player_t* player, char *filename); -sint_t aubio_midi_player_callback(void* data, uint_t msec); -sint_t aubio_midi_player_play(aubio_midi_player_t* player); -sint_t aubio_midi_player_play_offline(aubio_midi_player_t* player); -sint_t aubio_midi_player_stop(aubio_midi_player_t* player); -sint_t aubio_midi_player_set_loop(aubio_midi_player_t* player, sint_t loop); -sint_t aubio_midi_player_set_midi_tempo(aubio_midi_player_t* player, sint_t tempo); -sint_t aubio_midi_player_set_bpm(aubio_midi_player_t* player, sint_t bpm); -sint_t aubio_midi_player_join(aubio_midi_player_t* player); - -sint_t aubio_track_send_events(aubio_track_t* track, -/* aubio_synth_t* synth, */ - aubio_midi_player_t* player, - uint_t ticks); - -sint_t aubio_midi_send_event(aubio_midi_player_t* player, aubio_midi_event_t* event); -sint_t aubio_midi_receive_event(aubio_midi_player_t* player, aubio_midi_event_t* event); - -#ifdef __cplusplus -} -#endif - -#endif /* _AUBIO_MIDI_PLAYER_H*/ diff --git a/src/midi_track.c b/src/midi_track.c deleted file mode 100644 index 324c999f..00000000 --- a/src/midi_track.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License - * as published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - * 02111-1307, USA - */ - -/* this file originally taken from FluidSynth - A Software Synthesizer - * Copyright (C) 2003 Peter Hanappe and others. - */ - - -#include "aubio_priv.h" -#include "midi.h" -#include "midi_event.h" -#include "midi_track.h" -#include "midi_player.h" - - -/** new_aubio_track */ -aubio_track_t* new_aubio_track(int num) -{ - aubio_track_t* track; - track = AUBIO_NEW(aubio_track_t); - if (track == NULL) { - return NULL; - } - track->name = NULL; - track->num = num; - track->first = NULL; - track->cur = NULL; - track->last = NULL; - track->ticks = 0; - return track; -} - -/** del_aubio_track */ -int del_aubio_track(aubio_track_t* track) -{ - if (track->name != NULL) { - AUBIO_FREE(track->name); - } - if (track->first != NULL) { - del_aubio_midi_event(track->first); - } - AUBIO_FREE(track); - return AUBIO_OK; -} - -/** aubio_track_set_name */ -int aubio_track_set_name(aubio_track_t* track, char* name) -{ - int len; - if (track->name != NULL) { - AUBIO_FREE(track->name); - } - if (name == NULL) { - track->name = NULL; - return AUBIO_OK; - } - len = AUBIO_STRLEN(name); - track->name = AUBIO_MALLOC(len + 1); - if (track->name == NULL) { - AUBIO_ERR( "Out of memory"); - return AUBIO_FAIL; - } - AUBIO_STRCPY(track->name, name); - return AUBIO_OK; -} - -/** aubio_track_get_name */ -char* aubio_track_get_name(aubio_track_t* track) -{ - return track->name; -} - -/** aubio_track_get_duration */ -int aubio_track_get_duration(aubio_track_t* track) - { - int time = 0; - aubio_midi_event_t* evt = track->first; - while (evt != NULL) { - time += evt->dtime; - evt = evt->next; - } - return time; -} - -/** aubio_track_count_events */ -int aubio_track_count_events(aubio_track_t* track, int* on, int* off) -{ - aubio_midi_event_t* evt = track->first; - while (evt != NULL) { - if (evt->type == NOTE_ON) { - (*on)++; - } else if (evt->type == NOTE_OFF) { - (*off)++; - } - evt = evt->next; - } - return AUBIO_OK; -} - -/* - * aubio_track_add_event - */ -int aubio_track_add_event(aubio_track_t* track, aubio_midi_event_t* evt) -{ - evt->next = NULL; - if (track->first == NULL) { - track->first = evt; - track->cur = evt; - track->last = evt; - } else { - track->last->next = evt; - track->last = evt; - } - return AUBIO_OK; -} - -/* - * aubio_track_first_event - */ -aubio_midi_event_t* aubio_track_first_event(aubio_track_t* track) -{ - track->cur = track->first; - return track->cur; -} - -/* - * aubio_track_next_event - */ -aubio_midi_event_t* aubio_track_next_event(aubio_track_t* track) -{ - if (track->cur != NULL) { - track->cur = track->cur->next; - } - return track->cur; -} - -/* - * aubio_track_reset - */ - int -aubio_track_reset(aubio_track_t* track) -{ - track->ticks = 0; - track->cur = track->first; - return AUBIO_OK; -} - diff --git a/src/midi_track.h b/src/midi_track.h deleted file mode 100644 index 63f21962..00000000 --- a/src/midi_track.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License - * as published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - * 02111-1307, USA - */ - -/* this file originally taken from FluidSynth - A Software Synthesizer - * Copyright (C) 2003 Peter Hanappe and others. - */ - -#ifndef _AUBIO_MIDI_TRACK_H -#define _AUBIO_MIDI_TRACK_H - -/** \file - * midi track structure - * - * \bug need public declaration ? - */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** aubio_track_t */ -struct _aubio_track_t { - char* name; - int num; - aubio_midi_event_t *first; - aubio_midi_event_t *cur; - aubio_midi_event_t *last; - unsigned int ticks; -}; - -typedef struct _aubio_track_t aubio_track_t; - -aubio_track_t* new_aubio_track(int num); -int del_aubio_track(aubio_track_t* track); -int aubio_track_set_name(aubio_track_t* track, char* name); -char* aubio_track_get_name(aubio_track_t* track); -int aubio_track_add_event(aubio_track_t* track, aubio_midi_event_t* evt); -aubio_midi_event_t* aubio_track_first_event(aubio_track_t* track); -aubio_midi_event_t* aubio_track_next_event(aubio_track_t* track); -int aubio_track_get_duration(aubio_track_t* track); -int aubio_track_reset(aubio_track_t* track); -int aubio_track_count_events(aubio_track_t* track, int* on, int* off); - - -#define aubio_track_eot(track) ((track)->cur == NULL) - - -#ifdef __cplusplus -} -#endif - -#endif /*_AUBIO_MIDI_TRACK_H*/ diff --git a/src/timer.c b/src/timer.c deleted file mode 100644 index f78fe096..00000000 --- a/src/timer.c +++ /dev/null @@ -1,551 +0,0 @@ -/* - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License - * as published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - * 02111-1307, USA - */ - -/* this file originally taken from FluidSynth - A Software Synthesizer - * Copyright (C) 2003 Peter Hanappe and others. - */ - -#include "aubio_priv.h" -#include "timer.h" - -#if defined(WIN32) - -/*=============================================================*/ -/* */ -/* Win32 */ -/* */ -/*=============================================================*/ - -/*************************************************************** - * - * Timer - * - */ -#include - -#if 0 -#include - -struct _aubio_timer_t -{ - long msec; - aubio_timer_callback_t callback; - void* data; - HANDLE thread; - DWORD thread_id; - int cont; - int auto_destroy; -}; - -static int aubio_timer_count = 0; -DWORD WINAPI aubio_timer_run(LPVOID data); - -aubio_timer_t* -new_aubio_timer(int msec, aubio_timer_callback_t callback, void* data, - int new_thread, int auto_destroy) -{ - aubio_timer_t* timer = AUBIO_NEW(aubio_timer_t); - if (timer == NULL) { - AUBIO_ERR( "Out of memory"); - return NULL; - } - - timer->cont = 1; - timer->msec = msec; - timer->callback = callback; - timer->data = data; - timer->thread = 0; - timer->auto_destroy = auto_destroy; - - if (new_thread) { - timer->thread = CreateThread(NULL, 0, aubio_timer_run, (LPVOID) timer, 0, &timer->thread_id); - if (timer->thread == NULL) { - AUBIO_ERR( "Couldn't create timer thread"); - AUBIO_FREE(timer); - return NULL; - } - SetThreadPriority(timer->thread, THREAD_PRIORITY_TIME_CRITICAL); - } else { - aubio_timer_run((LPVOID) timer); - } - return timer; -} - -DWORD WINAPI -aubio_timer_run(LPVOID data) -{ - int count = 0; - int cont = 1; - long start; - long delay; - aubio_timer_t* timer; - timer = (aubio_timer_t*) data; - - if ((timer == NULL) || (timer->callback == NULL)) { - return 0; - } - - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); - - /* keep track of the start time for absolute positioning */ - start = aubio_curtime(); - - while (cont) { - - /* do whatever we have to do */ - cont = (*timer->callback)(timer->data, aubio_curtime() - start); - - count++; - - /* to avoid incremental time errors, I calculate the delay between - two callbacks bringing in the "absolute" time (count * - timer->msec) */ - delay = (count * timer->msec) - (aubio_curtime() - start); - if (delay > 0) { - Sleep(delay); - } - - cont &= timer->cont; - } - - AUBIO_DBG( "Timer thread finished"); - - if (timer->auto_destroy) { - AUBIO_FREE(timer); - } - - ExitThread(0); - return 0; -} - -int -delete_aubio_timer(aubio_timer_t* timer) -{ - timer->cont = 0; - aubio_timer_join(timer); - AUBIO_FREE(timer); - return AUBIO_OK; -} - -int -aubio_timer_join(aubio_timer_t* timer) -{ - DWORD wait_result; - if (timer->thread == 0) { - return AUBIO_OK; - } - wait_result = WaitForSingleObject(timer->thread, INFINITE); - return (wait_result == WAIT_OBJECT_0)? AUBIO_OK : AUBIO_FAIL; -} -/*************************************************************** - * - * Time - */ - -double rdtsc(void); -double aubio_estimate_cpu_frequency(void); - -static double aubio_cpu_frequency = -1.0; - -void aubio_time_config(void) -{ - if (aubio_cpu_frequency < 0.0) { - aubio_cpu_frequency = aubio_estimate_cpu_frequency() / 1000000.0; - } -} - -double aubio_utime(void) -{ - return (rdtsc() / aubio_cpu_frequency); -} - -double rdtsc(void) -{ - LARGE_INTEGER t; - QueryPerformanceCounter(&t); - return (double) t.QuadPart; -} - -double aubio_estimate_cpu_frequency(void) -{ -#if 0 - LONGLONG start, stop, ticks; - unsigned int before, after, delta; - double freq; - - start = rdtsc(); - stop = start; - before = aubio_curtime(); - after = before; - - while (1) { - if (after - before > 1000) { - break; - } - after = aubio_curtime(); - stop = rdtsc(); - } - - delta = after - before; - ticks = stop - start; - - freq = 1000 * ticks / delta; - - return freq; - -#else - unsigned int before, after; - LARGE_INTEGER start, stop; - - before = aubio_curtime(); - QueryPerformanceCounter(&start); - - Sleep(1000); - - after = aubio_curtime(); - QueryPerformanceCounter(&stop); - - return (double) 1000 * (stop.QuadPart - start.QuadPart) / (after - before); -#endif -} - -#endif - - -#elif defined(MACOS9) -/*=============================================================*/ -/* */ -/* MacOS 9 */ -/* */ -/*=============================================================*/ - - -/*************************************************************** - * - * Timer - */ - -struct _aubio_timer_t -{ - TMTask myTmTask; - long msec; - unsigned int start; - unsigned int count; - int isInstalled; - aubio_timer_callback_t callback; - void* data; - int auto_destroy; -}; - -static TimerUPP myTimerUPP; - -void -_timerCallback(aubio_timer_t *timer) -{ - int cont; - cont = (*timer->callback)(timer->data, aubio_curtime() - timer->start); - if (cont) { - PrimeTime((QElemPtr)timer, timer->msec); - } else { - timer->isInstalled = 0; - } - timer->count++; -} - -aubio_timer_t* -new_aubio_timer(int msec, aubio_timer_callback_t callback, void* data, - int new_thread, int auto_destroy) -{ - aubio_timer_t* timer = AUBIO_NEW(aubio_timer_t); - if (timer == NULL) { - AUBIO_ERR( "Out of memory"); - return NULL; - } - - if (!myTimerUPP) - myTimerUPP = NewTimerProc(_timerCallback); - - /* setup tmtask */ - timer->myTmTask.tmAddr = myTimerUPP; - timer->myTmTask.qLink = NULL; - timer->myTmTask.qType = 0; - timer->myTmTask.tmCount = 0L; - timer->myTmTask.tmWakeUp = 0L; - timer->myTmTask.tmReserved = 0L; - - timer->callback = callback; - - timer->msec = msec; - timer->data = data; - timer->start = aubio_curtime(); - timer->isInstalled = 1; - timer->count = 0; - timer->auto_destroy = auto_destroy; - - InsXTime((QElemPtr)timer); - PrimeTime((QElemPtr)timer, msec); - - return timer; -} - -int -delete_aubio_timer(aubio_timer_t* timer) -{ - if (timer->isInstalled) { - RmvTime((QElemPtr)timer); - } - AUBIO_FREE(timer); - return AUBIO_OK; -} - -int -aubio_timer_join(aubio_timer_t* timer) -{ - if (timer->isInstalled) { - int count = timer->count; - /* wait until count has incremented */ - while (count == timer->count) {} - } - return AUBIO_OK; -} - -/*************************************************************** - * - * Time - */ -#define kTwoPower32 (4294967296.0) /* 2^32 */ - -void aubio_time_config(void) -{ -} - -unsigned int aubio_curtime() -{ - /* could be optimized by not going though a double */ - UnsignedWide uS; - double mSf; - unsigned int ms; - - Microseconds(&uS); - - mSf = ((((double) uS.hi) * kTwoPower32) + uS.lo)/1000.0f; - - ms = mSf; - - return (ms); -} - - - -#else - -/*=============================================================*/ -/* */ -/* POSIX */ -/* */ -/*=============================================================*/ - -#include -#include -#include - - -/*************************************************************** - * - * Timer - */ - -struct _aubio_timer_t -{ - long msec; - aubio_timer_callback_t callback; - void* data; - pthread_t thread; - int cont; - int auto_destroy; -}; - -void* -aubio_timer_start(void *data) -{ - int count = 0; - int cont = 1; - long start; - long delay; - aubio_timer_t* timer; - timer = (aubio_timer_t*) data; - - /* keep track of the start time for absolute positioning */ - start = aubio_curtime(); - - while (cont) { - - /* do whatever we have to do */ - cont = (*timer->callback)(timer->data, aubio_curtime() - start); - - count++; - - /* to avoid incremental time errors, calculate the delay between - two callbacks bringing in the "absolute" time (count * - timer->msec) */ - delay = (count * timer->msec) - (aubio_curtime() - start); - if (delay > 0) { - usleep(delay * 1000); - } - - cont &= timer->cont; - } - - AUBIO_DBG( "Timer thread finished"); - if (timer->thread != 0) { - pthread_exit(NULL); - } - - if (timer->auto_destroy) { - AUBIO_FREE(timer); - } - - return NULL; -} - -aubio_timer_t* -new_aubio_timer(int msec, aubio_timer_callback_t callback, void* data, - int new_thread, int auto_destroy) -{ - aubio_timer_t* timer = AUBIO_NEW(aubio_timer_t); - if (timer == NULL) { - AUBIO_ERR( "Out of memory"); - return NULL; - } - timer->msec = msec; - timer->callback = callback; - timer->data = data; - timer->cont = 1; - timer->thread = 0; - timer->auto_destroy = auto_destroy; - - if (new_thread) { - if (pthread_create(&timer->thread, NULL, aubio_timer_start, (void*) timer)) { - AUBIO_ERR( "Failed to create the timer thread"); - AUBIO_FREE(timer); - return NULL; - } - } else { - aubio_timer_start((void*) timer); - } - return timer; -} - -int -delete_aubio_timer(aubio_timer_t* timer) -{ - timer->cont = 0; - aubio_timer_join(timer); - AUBIO_DBG( "Deleted player thread\n"); - AUBIO_FREE(timer); - return AUBIO_OK; -} - -int -aubio_timer_join(aubio_timer_t* timer) -{ - int err = 0; - - if (timer->thread != 0) { - err = pthread_join(timer->thread, NULL); - } else - AUBIO_DBG( "Joined player thread\n"); - return (err == 0)? AUBIO_OK : AUBIO_FAIL; -} - - -/*************************************************************** - * - * Time - */ - -static double aubio_cpu_frequency = -1.0; - -double rdtsc(void); -double aubio_estimate_cpu_frequency(void); - -void aubio_time_config(void) -{ - if (aubio_cpu_frequency < 0.0) { - aubio_cpu_frequency = aubio_estimate_cpu_frequency() / 1000000.0; - } -} - -unsigned int aubio_curtime() -{ - struct timeval now; - gettimeofday(&now, NULL); - return now.tv_sec * 1000 + now.tv_usec / 1000; -} - -double aubio_utime(void) -{ - return (rdtsc() / aubio_cpu_frequency); -} - -#if !defined(__i386__) - -double rdtsc(void) -{ - return 0.0; -} - -double aubio_estimate_cpu_frequency(void) -{ - return 1.0; -} - -#else - -double rdtsc(void) -{ - unsigned int a, b; - - __asm__ ("rdtsc" : "=a" (a), "=d" (b)); - return (double)b * (double)0x10000 * (double)0x10000 + a; -} - -double aubio_estimate_cpu_frequency(void) -{ - double start, stop; - unsigned int a0, b0, a1, b1; - unsigned int before, after; - - before = aubio_curtime(); - __asm__ ("rdtsc" : "=a" (a0), "=d" (b0)); - - sleep(1); - - after = aubio_curtime(); - __asm__ ("rdtsc" : "=a" (a1), "=d" (b1)); - - - start = (double)b0 * (double)0x10000 * (double)0x10000 + a0; - stop = (double)b1 * (double)0x10000 * (double)0x10000 + a1; - - return 1000 * (stop - start) / (after - before); -} - -#endif - -#endif diff --git a/src/timer.h b/src/timer.h deleted file mode 100644 index 582fe925..00000000 --- a/src/timer.h +++ /dev/null @@ -1,34 +0,0 @@ - -#if defined(WIN32) -#define aubio_curtime() GetTickCount() - -double aubio_utime(void); - -#elif defined(MACOS9) -#include -#include - -unsigned int aubio_curtime(); -#define aubio_utime() 0.0 - -#else - -unsigned int aubio_curtime(void); -double aubio_utime(void); - -#endif - -/* if the callback function returns 1 the timer will continue; if it - returns 0 it will stop */ -typedef int (*aubio_timer_callback_t)(void* data, unsigned int msec); - -typedef struct _aubio_timer_t aubio_timer_t; - -aubio_timer_t* new_aubio_timer(int msec, aubio_timer_callback_t callback, - void* data, int new_thread, int auto_destroy); - -int delete_aubio_timer(aubio_timer_t* timer); -int aubio_timer_join(aubio_timer_t* timer); -int aubio_timer_stop(aubio_timer_t* timer); -void * aubio_timer_start(void * data); -void aubio_time_config(void);