diff --git a/src/gui/midi.cpp b/src/gui/midi.cpp index bbbb2d9c..ebc8550e 100644 --- a/src/gui/midi.cpp +++ b/src/gui/midi.cpp @@ -24,8 +24,12 @@ #include "cross.h" #include "support.h" #include "setup.h" +#include "mapper.h" +#include "pic.h" +#include "hardware.h" #define SYSEX_SIZE 1024 +#define RAWBUF 1024 Bit8u MIDI_evt_len[256] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x00 @@ -47,7 +51,7 @@ Bit8u MIDI_evt_len[256] = { 3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, // 0xe0 - 0,2,3,2, 0,0,1,1, 1,0,1,1, 1,0,1,1 // 0xf0 + 0,2,3,2, 0,0,1,0, 1,0,1,1, 1,0,1,1 // 0xf0 }; class MidiHandler; @@ -62,7 +66,7 @@ public: }; virtual bool Open(const char * conf) { return true; }; virtual void Close(void) {}; - virtual void PlayMsg(Bit32u msg) {}; + virtual void PlayMsg(Bit8u * msg) {}; virtual void PlaySysex(Bit8u * sysex,Bitu len) {}; virtual char * GetName(void) { return "none"; }; MidiHandler * next; @@ -96,49 +100,117 @@ static struct { Bitu status; Bitu cmd_len; Bitu cmd_pos; - - Bit32u cmd_msg; - Bit8u data[4]; + Bit8u cmd_buf[8]; struct { Bit8u buf[SYSEX_SIZE]; Bitu used; - bool active; } sysex; bool available; MidiHandler * handler; + struct { + FILE * handle; + Bit8u buffer[RAWBUF+SYSEX_SIZE]; + Bitu used,done; + Bit32u last; + } raw; } midi; +static Bit8u midi_header[]={ + 'M','T','h','d', /* Bit32u, Header Chunk */ + 0x0,0x0,0x0,0x6, /* Bit32u, Chunk Length */ + 0x0,0x0, /* Bit16u, Format, 0=single track */ + 0x0,0x1, /* Bit16u, Track Count, 1 track */ + 0x01,0xf4, /* Bit16u, Timing, 2 beats/second with 500 frames */ + 'M','T','r','k', /* Bit32u, Track Chunk */ + 0x0,0x0,0x0,0x0, /* Bit32u, Chunk Length */ + //Track data +}; + +#define ADDBUF(_VAL_) midi.raw.buffer[midi.raw.used++]=(Bit8u)(_VAL_); +static INLINE void RawAddNumber(Bit32u val) { + if (val & 0xfe00000) ADDBUF(0x80|((val >> 21) & 0x7f)); + if (val & 0xfffc000) ADDBUF(0x80|((val >> 14) & 0x7f)); + if (val & 0xfffff80) ADDBUF(0x80|((val >> 7) & 0x7f)); + ADDBUF(val & 0x7f); +} +static INLINE void RawAddDelta(void) { + if (!midi.raw.last) midi.raw.last=PIC_Ticks; + Bit32u delta=PIC_Ticks-midi.raw.last; + midi.raw.last=PIC_Ticks; + RawAddNumber(delta); +} + +static INLINE void RawAddData(Bit8u * data,Bitu len) { + for (Bitu i=0;i=RAWBUF) { + fwrite(midi.raw.buffer,1,midi.raw.used,midi.raw.handle); + midi.raw.done+=midi.raw.used; + midi.raw.used=0; + } +} + +static void MIDI_SaveRawEvent(void) { + /* Check for previously opened wave file */ + if (midi.raw.handle) { + LOG_MSG("Stopping raw midi saving."); + ADDBUF(0x00);//Delta time + ADDBUF(0xff);ADDBUF(0x2F);ADDBUF(0x00); //End of track event + fwrite(midi.raw.buffer,1,midi.raw.used,midi.raw.handle); + midi.raw.done+=midi.raw.used; + fseek(midi.raw.handle,18, SEEK_SET); + Bit8u size[4]; + size[0]=(Bit8u)(midi.raw.done >> 24); + size[1]=(Bit8u)(midi.raw.done >> 16); + size[2]=(Bit8u)(midi.raw.done >> 8); + size[3]=(Bit8u)(midi.raw.done >> 0); + fwrite(&size,1,4,midi.raw.handle); + fclose(midi.raw.handle); + midi.raw.handle=0; + } else { + midi.raw.handle=OpenCaptureFile("Raw Midi",".mid"); + if (!midi.raw.handle) return; + fwrite(midi_header,1,sizeof(midi_header),midi.raw.handle); + midi.raw.used=0; + midi.raw.done=0; + } +} + + void MIDI_RawOutByte(Bit8u data) { - /* Test for a new status byte */ - if (midi.sysex.active && !(data&0x80)) { - if (midi.sysex.used<(SYSEX_SIZE-1)) midi.sysex.buf[midi.sysex.used++]=data; - return; - } else if (data&0x80) { - if (midi.sysex.active) { - /* Play a sysex message */ + /* Test for a active sysex tranfer */ + if (midi.status==0xf0) { + if (!(data&0x80)) { + if (midi.sysex.used<(SYSEX_SIZE-1)) midi.sysex.buf[midi.sysex.used++]=data; + return; + } else { midi.sysex.buf[midi.sysex.used++]=0xf7; midi.handler->PlaySysex(midi.sysex.buf,midi.sysex.used); LOG(LOG_ALL,LOG_NORMAL)("Sysex message size %d",midi.sysex.used); - midi.sysex.active=false; - if (data==0xf7) return; + if (midi.raw.handle) { + RawAddDelta(); + ADDBUF(0xf0); + RawAddNumber(midi.sysex.used-1); + RawAddData(&midi.sysex.buf[1],midi.sysex.used-1); + } } + } + if (data&0x80) { midi.status=data; midi.cmd_pos=0; - midi.cmd_msg=0; + midi.cmd_len=MIDI_evt_len[data]; if (midi.status==0xf0) { - midi.sysex.active=true; midi.sysex.buf[0]=0xf0; midi.sysex.used=1; - return; } - midi.cmd_len=MIDI_evt_len[data]; } - midi.cmd_msg|=data << (8 * midi.cmd_pos); - midi.cmd_pos++; - if (midi.cmd_pos >= midi.cmd_len) { - midi.handler->PlayMsg(midi.cmd_msg); - midi.cmd_msg=midi.status; - midi.cmd_pos=1; + midi.cmd_buf[midi.cmd_pos++]=data; + if (midi.cmd_len && midi.cmd_pos >= midi.cmd_len) { + if (midi.raw.handle) { + RawAddDelta(); + RawAddData(midi.cmd_buf,midi.cmd_len); + } + midi.handler->PlayMsg(midi.cmd_buf); + midi.cmd_pos=1; //Use Running status } } @@ -146,12 +218,21 @@ bool MIDI_Available(void) { return midi.available; } +static void MIDI_Stop(Section* sec) { + if (midi.raw.handle) MIDI_SaveRawEvent(); +} + void MIDI_Init(Section * sec) { Section_prop * section=static_cast(sec); const char * dev=section->Get_string("device"); const char * conf=section->Get_string("config"); /* If device = "default" go for first handler that works */ MidiHandler * handler; + MAPPER_AddHandler(MIDI_SaveRawEvent,MK_f8,MMOD1|MMOD2,"caprawmidi","Cap MIDI"); + sec->AddDestroyFunction(&MIDI_Stop); + midi.status=0x00; + midi.cmd_pos=0; + midi.cmd_len=0; if (!strcasecmp(dev,"default")) goto getdefault; handler=handler_list; while (handler) { @@ -180,6 +261,5 @@ getdefault: handler=handler->next; } /* This shouldn't be possible */ - midi.available=false; } diff --git a/src/gui/midi_alsa.h b/src/gui/midi_alsa.h index 988f98b0..7a10910a 100644 --- a/src/gui/midi_alsa.h +++ b/src/gui/midi_alsa.h @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: midi_alsa.h,v 1.7 2004-01-26 15:10:16 qbix79 Exp $ */ +/* $Id: midi_alsa.h,v 1.8 2004-07-04 21:08:08 harekiet Exp $ */ #define ALSA_PCM_OLD_HW_PARAMS_API #define ALSA_PCM_OLD_SW_PARAMS_API @@ -75,45 +75,38 @@ public: send_event(1); } - void PlayMsg(Bit32u msg) { + void PlayMsg(Bit8u * msg) { unsigned int midiCmd[4]; ev.type = SND_SEQ_EVENT_OSS; - if (msg == 247) // to accomadate lure of the temptress - return; + ev.data.raw32.d[0] = msg[0]; + ev.data.raw32.d[1] = msg[1]; + ev.data.raw32.d[2] = msg[2]; - midiCmd[3] = (msg & 0xFF000000) >> 24; - midiCmd[2] = (msg & 0x00FF0000) >> 16; - midiCmd[1] = (msg & 0x0000FF00) >> 8; - midiCmd[0] = (msg & 0x000000FF); - ev.data.raw32.d[0] = midiCmd[0]; - ev.data.raw32.d[1] = midiCmd[1]; - ev.data.raw32.d[2] = midiCmd[2]; - - unsigned char chanID = midiCmd[0] & 0x0F; - switch (midiCmd[0] & 0xF0) { + unsigned char chanID = msg[0] & 0x0F; + switch (msg[0] & 0xF0) { case 0x80: - snd_seq_ev_set_noteoff(&ev, chanID, midiCmd[1], midiCmd[2]); + snd_seq_ev_set_noteoff(&ev, chanID, msg[1], msg[2]); send_event(1); break; case 0x90: - snd_seq_ev_set_noteon(&ev, chanID, midiCmd[1], midiCmd[2]); + snd_seq_ev_set_noteon(&ev, chanID, msg[1], msg[2]); send_event(1); break; case 0xB0: - snd_seq_ev_set_controller(&ev, chanID, midiCmd[1], midiCmd[2]); + snd_seq_ev_set_controller(&ev, chanID, msg[1], msg[2]); send_event(1); break; case 0xC0: - snd_seq_ev_set_pgmchange(&ev, chanID, midiCmd[1]); + snd_seq_ev_set_pgmchange(&ev, chanID, msg[1]); send_event(0); break; case 0xD0: - snd_seq_ev_set_chanpress(&ev, chanID, midiCmd[1]); + snd_seq_ev_set_chanpress(&ev, chanID, msg[1]); send_event(0); break; case 0xE0:{ - long theBend = ((long)midiCmd[1] + (long)(midiCmd[2] << 7)) - 0x2000; + long theBend = ((long)msg[1] + (long)(msg[2] << 7)) - 0x2000; snd_seq_ev_set_pitchbend(&ev, chanID, theBend); send_event(1); } diff --git a/src/gui/midi_coreaudio.h b/src/gui/midi_coreaudio.h index 0d7f9635..349c6da3 100644 --- a/src/gui/midi_coreaudio.h +++ b/src/gui/midi_coreaudio.h @@ -76,12 +76,8 @@ public: } } - void PlayMsg(Bit32u msg) { - MusicDeviceMIDIEvent(m_musicDevice, - (msg & 0x000000FF), - (msg & 0x0000FF00) >> 8, - (msg & 0x00FF0000) >> 16, - 0); + void PlayMsg(Bit8u * msg) { + MusicDeviceMIDIEvent(m_musicDevice,msg[0],msg[1],msg[2],0); } void PlaySysex(Bit8u * sysex, Bitu len) { diff --git a/src/gui/midi_oss.h b/src/gui/midi_oss.h index 62e1dfaf..d770a12a 100644 --- a/src/gui/midi_oss.h +++ b/src/gui/midi_oss.h @@ -45,15 +45,15 @@ public: if (!isOpen) return; if (device>0) close(device); }; - void PlayMsg(Bit32u msg) { + void PlayMsg(Bit8u * msg) { Bit8u buf[128];Bitu pos=0; Bitu len=MIDI_evt_len[msg & 0xff]; for (;len>0;len--) { buf[pos++] = SEQ_MIDIPUTC; - buf[pos++] = msg & 0xff; + buf[pos++] = *msg; buf[pos++] = device_num; buf[pos++] = 0; - msg >>=8; + msg++; } write(device,buf,pos); }; diff --git a/src/gui/midi_win32.h b/src/gui/midi_win32.h index b08652b6..e9a8651f 100644 --- a/src/gui/midi_win32.h +++ b/src/gui/midi_win32.h @@ -42,8 +42,8 @@ public: midiOutClose(m_out); CloseHandle (m_event); }; - void PlayMsg(Bit32u msg) { - midiOutShortMsg(m_out, msg); + void PlayMsg(Bit8u * msg) { + midiOutShortMsg(m_out, *(Bit32u*)msg); }; void PlaySysex(Bit8u * sysex,Bitu len) { if (WaitForSingleObject (m_event, 2000) == WAIT_TIMEOUT) {