📄 midi.c
字号:
/*================================================================== * midi.c - Midi thru functions (driver independant) * * Smurf Sound Font Editor * Copyright (C) 1999-2001 Josh Green * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA or point your web browser to http://www.gnu.org. * * To contact the author of this program: * Email: Josh Green <jgreen@users.sourceforge.net> * Smurf homepage: http://smurf.sourceforge.net *==================================================================*/#include "config.h"#include <stdio.h>#include <unistd.h>#include <fcntl.h>#include <string.h>#include <glib.h>#include "uif_sfont.h"#include "midi.h"#include "widgets/piano.h"#include "uif_piano.h"#include "sfont.h"#include "sequencer.h"#include "smurfcfg.h"#include "util.h"#include "i18n.h"#include "drivers/midi_alsaseq.h"#include "drivers/midi_alsaraw.h"#include "drivers/midi_oss.h"MidiDriverInfo midi_drivers[] = { {N_("NONE"), NULL, NULL, NULL},#ifdef ALSA_SUPPORT {N_("ALSA_SEQ"), /* ALSA direct connection between 2 ports */ midi_alsaseq_load_config, midi_alsaseq_init, midi_alsaseq_close, NULL }, {N_("ALSA_RAW"), /* ALSA raw software midi thru */ midi_alsaraw_load_config, midi_alsaraw_init, midi_alsaraw_close, midi_alsaraw_read },#endif#ifdef OSS_SUPPORT {N_("OSS"), NULL, midi_oss_init, midi_oss_close, midi_oss_read }#endif};gint midi_driver = MIDI_NONE; /* active midi driver */gint midi_active = FALSE; /* state of midi device */gint midi_bank = 0; /* current active bank # */gint midi_preset = 0; /* current active preset # */gint midi_bend = 0x2000; /* current midi bender value */static guint8 midibuf[100]; /* circular midi buffer */static guint8 midindx; /* current index in midibuf */static guint8 midirun; /* current status running byte or 0 */static guint8 mididat = 0xFF; /* 1st data byte for 2 byte ops *//* update MIDI variables from config and init driver appropriately */gintmidi_init_from_config (void){ GTokenValue *val; gint drvr_id; gboolean retval; gint i; /* load config for each MIDI driver */ for (i = 0; i < MIDI_COUNT; i++) if (midi_drivers[i].config) (*midi_drivers[i].config) (); val = smurfcfg_get_val (SMURFCFG_MIDI_DRIVER); if (strcmp (val->v_string, "AUTO") != 0 && (drvr_id = midi_locate_byname (val->v_string)) != -1) { log_message (_("Initializing MIDI thru driver \"%s\".."),val->v_string); midi_set_driver (drvr_id); retval = midi_init (); if (retval) log_message (_("MIDI thru driver initialized")); else logit (LogFubar, _("MIDI thru driver failed")); return (retval); } else return (midi_auto_init ());}/* "AUTO" detect and initialize supported MIDI driver */gintmidi_auto_init (void){ gint i; gchar *name; log_message (_("Looking for supported MIDI driver..")); if (MIDI_COUNT == 1) { log_message (_("No MIDI drivers were compiled into Smurf!")); return (FAIL); } for (i = 1; i < MIDI_COUNT; i++) { name = _(midi_drivers[i].name); log_message (_("Trying driver %s..."), name); midi_set_driver (i); if (midi_init ()) { log_message (_("Initialization of %s driver successful"), name); return (OK); } else log_message (_("Driver %s failed"), name); } log_message (_("No MIDI support found!")); return (FAIL);}/* finds the MIDI driver id for a given MIDI driver name */gintmidi_locate_byname (gchar * name){ gint i; for (i = 0; i < MIDI_COUNT; i++) { if (strcmp (name, midi_drivers[i].name) == 0) return (i); } return (-1);}/* set active driver type, OSS/ALSA */voidmidi_set_driver (gint driver){ if (driver >= MIDI_COUNT) return; midi_driver = driver;}/* initialize active midi driver */gintmidi_init (void){ if (midi_active) return (OK); if (!midi_drivers[midi_driver].init) return (OK); /* init function? */ if (!(*midi_drivers[midi_driver].init) ()) return (FAIL); midi_active = TRUE; midindx = midirun = 0; return (OK);}/* close active midi driver */gintmidi_close (void){ if (!midi_active) return (OK); if (!midi_drivers[midi_driver].close) return (OK); /* close function? */ (*midi_drivers[midi_driver].close) (); /* run drivers close routine */ midi_active = FALSE; return (OK);}/* read and parse midi input from active driver */voidmidi_read (void){ gint i; guint8 b; /* stores current byte */ guint8 ch; /* channel (for voice messages) */// SFGenAmount amt; if (!midi_drivers[midi_driver].read) return; if ((i = (*midi_drivers[midi_driver].read) (&midibuf[midindx], sizeof (midibuf) - midindx)) < 0) return; midindx += i; i = 0; while (i < midindx) { b = midibuf[i]; i++; if (b & 0x80) { /* status byte? */ if (b < 0xF0) { /* voice message? */ midirun = b; /* set running status byte op */ mididat = 0xFF; /* for 2 byte ops */ } else if (b < 0xF8) midirun = 0; /* discard data after sys msg */ continue; /* discard real time bytes */ } /* current byte is data */ if (!midirun) continue; /* must be voice message */ ch = midirun & 0x0F; /* channel */ switch (midirun & 0xF0) { case 0x80: /* note off */ if (mididat == 0xFF) { mididat = b; break; } seq_note_off (ch, mididat, b); /* else note off */ piano_note_off (PIANO (uipiano_widg), mididat); mididat = 0xFF; break; case 0x90: /* note on */ if (mididat == 0xFF) { mididat = b; break; } if (b) { seq_note_on (ch, mididat, b); /* if vel > 0 note_on */ piano_note_on (PIANO (uipiano_widg), mididat); } else { seq_note_off (ch, mididat, 0); /* else note off */ piano_note_off (PIANO (uipiano_widg), mididat); } mididat = 0xFF; break; case 0xA0: /* key pressure */ if (mididat == 0xFF) { mididat = b; break; } mididat = 0xFF; break; case 0xB0: /* parameter */ if (mididat == 0xFF) { mididat = b; break; } if (mididat == 0x5D) seq_chorus (ch, b); else if (mididat == 0x5B) seq_reverb (ch, b); mididat = 0xFF; break; case 0xC0: /* program */ seq_set_preset (ch, b); break; case 0xD0: /* chan pressure */ break; case 0xE0: /* pitch wheel */ if (mididat == 0xFF) { mididat = b; break; } seq_pitch_bender(ch, (mididat & 0x7F) | ((b & 0x7F) << 7));/* having fun with some what "real time" AWE effects :) */// amt.sword = (mididat & 0x7F) | ((b & 0x7F) << 7);// seq_set_effect (ch, Gen_FilterFc, amt); mididat = 0xFF; break; } } midindx = 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -