ref: b625cffaaaddff5d84483382c083652dac1394f3
parent: 0517615df8ab283df2f09ab29f15827f26914b58
author: unknown <fabien@fabien-PC.(none)>
date: Sat Dec 15 11:27:41 EST 2012
Removed Windows specifc code in Music engine: Relying fully on SDL_Mixer now.
--- a/Game/Game.vcxproj
+++ b/Game/Game.vcxproj
@@ -127,6 +127,7 @@
<ClCompile Include="src\global.c" />
<ClCompile Include="src\keyboard.c" />
<ClCompile Include="src\menues.c" />
+ <ClCompile Include="src\midi\sdl_midi.c" />
<ClCompile Include="src\player.c" />
<ClCompile Include="src\premap.c" />
<ClCompile Include="src\rts.c" />
@@ -133,8 +134,6 @@
<ClCompile Include="src\scriplib.c" />
<ClCompile Include="src\sector.c" />
<ClCompile Include="src\sounds.c" />
- <ClCompile Include="src\midi\win_midiout.cpp" />
- <ClCompile Include="src\midi\xmidi.cpp" />
<ClCompile Include="src\audiolib\dsl.c" />
<ClCompile Include="src\audiolib\fx_man.c">
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)%(Filename)1.obj</ObjectFileName>
@@ -172,9 +171,6 @@
<ClInclude Include="src\sounds.h" />
<ClInclude Include="src\types.h" />
<ClInclude Include="src\util_lib.h" />
- <ClInclude Include="src\midi\databuf.h" />
- <ClInclude Include="src\midi\win_midiout.h" />
- <ClInclude Include="src\midi\xmidi.h" />
<ClInclude Include="src\audiolib\assert.h" />
<ClInclude Include="src\_functio.h" />
<ClInclude Include="src\console.h" />
--- a/Game/Game.vcxproj.filters
+++ b/Game/Game.vcxproj.filters
@@ -68,12 +68,6 @@
<ClCompile Include="src\sounds.c">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\midi\win_midiout.cpp">
- <Filter>Midi</Filter>
- </ClCompile>
- <ClCompile Include="src\midi\xmidi.cpp">
- <Filter>Midi</Filter>
- </ClCompile>
<ClCompile Include="src\audiolib\dsl.c">
<Filter>Audiolib</Filter>
</ClCompile>
@@ -110,6 +104,9 @@
<ClCompile Include="src\cvars.c">
<Filter>Console Source</Filter>
</ClCompile>
+ <ClCompile Include="src\midi\sdl_midi.c">
+ <Filter>Midi</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\_rts.h">
@@ -171,15 +168,6 @@
</ClInclude>
<ClInclude Include="src\util_lib.h">
<Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\midi\databuf.h">
- <Filter>Midi</Filter>
- </ClInclude>
- <ClInclude Include="src\midi\win_midiout.h">
- <Filter>Midi</Filter>
- </ClInclude>
- <ClInclude Include="src\midi\xmidi.h">
- <Filter>Midi</Filter>
</ClInclude>
<ClInclude Include="src\audiolib\assert.h">
<Filter>Audiolib</Filter>
--- a/Game/src/audiolib/music.h
+++ b/Game/src/audiolib/music.h
@@ -31,7 +31,7 @@
#ifndef __MUSIC_H
#define __MUSIC_H
-#include "duke3d.h"
+#include "../duke3d.h"
#include "sndcards.h"
@@ -81,7 +81,7 @@
void MUSIC_Continue( void );
void MUSIC_Pause( void );
int MUSIC_StopSong( void );
-int MUSIC_PlaySong( char *song, int loopflag );
+int MUSIC_PlaySong( uint8_t* songData, int loopflag );
void MUSIC_SetContext( int context );
int MUSIC_GetContext( void );
void MUSIC_SetSongTick( uint32_t PositionInTicks );
--- a/Game/src/midi/databuf.h
+++ /dev/null
@@ -1,230 +1,0 @@
-/*
- * 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 Library General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * aint32_t with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef DATA_H
-#define DATA_H
-
-#ifdef _WIN32
- #include "../../../Engine/src/windows/inttypes.h"
-#else
- #include <inttypes.h>
-#endif
-
-#ifndef ALPHA_LINUX_CXX
-# include <cstdio>
-# include <cstring>
-#endif
-#ifdef MACOS
-# include <cassert>
-#endif
-#include <fstream>
-#include <iomanip>
-
-
-/*
-typedef uint8_t uint8;
-typedef unsigned short uint16;
-typedef uint32_t uint32;
-
-typedef int8_t sint8;
-typedef signed short sint16;
-typedef int32_t sint32;
-*/
-
-class DataSource
-{
-protected:
- union uint_float {
- uint32_t i;
- float f;
- };
-
-public:
- DataSource() {};
- virtual ~DataSource() {};
-
- virtual unsigned int read1() =0;
- virtual uint16_t read2() =0;
- virtual uint16_t read2high() =0;
- virtual uint32_t read4() =0;
- virtual uint32_t read4high() =0;
- virtual float readf() =0;
- virtual void read(uint8_t *, int32_t) =0;
-
- virtual void write1(uint32_t) =0;
- virtual void write2(uint16_t) =0;
- virtual void write2high(uint16_t) =0;
- virtual void write4(uint32_t) =0;
- virtual void write4high(uint32_t) =0;
- virtual void writef(float) =0;
- virtual void write(uint8_t *, int) =0;
-
- virtual void seek(unsigned int) =0;
- virtual void skip(int) =0;
- virtual unsigned int getSize() =0;
- virtual unsigned int getPos() =0;
-};
-
-class BufferDataSource: public DataSource
-{
-protected:
- /* const solely so that no-one accidentally modifies it.
- data is being passed 'non-const' anyway */
- const uint8_t *buf;
- uint8_t *buf_ptr;
- int32_t size;
-public:
- BufferDataSource(uint8_t *data, unsigned int len)
- {
- // data can be NULL if len is also 0
-// assert(data!=0 || len==0);
- buf = buf_ptr = reinterpret_cast<uint8_t *>(data);
- size = len;
- };
-
- void load(uint8_t *data, unsigned int len)
- {
- // data can be NULL if len is also 0
- //assert(data!=0 || len==0);
- buf = buf_ptr = reinterpret_cast<uint8_t *>(data);
- size = len;
- };
-
- virtual ~BufferDataSource() {};
-
- virtual unsigned int read1()
- {
- uint8_t b0;
- b0 = static_cast<uint8_t >(*buf_ptr++);
- return (b0);
- };
-
- virtual uint16_t read2()
- {
- uint8_t b0, b1;
- b0 = static_cast<uint8_t >(*buf_ptr++);
- b1 = static_cast<uint8_t >(*buf_ptr++);
- return (b0 | (b1 << 8));
- };
-
- virtual uint16_t read2high()
- {
- uint8_t b0, b1;
- b1 = static_cast<uint8_t >(*buf_ptr++);
- b0 = static_cast<uint8_t >(*buf_ptr++);
- return (b0 | (b1 << 8));
- };
-
- virtual uint32_t read4()
- {
- uint8_t b0, b1, b2, b3;
- b0 = static_cast<uint8_t >(*buf_ptr++);
- b1 = static_cast<uint8_t >(*buf_ptr++);
- b2 = static_cast<uint8_t >(*buf_ptr++);
- b3 = static_cast<uint8_t >(*buf_ptr++);
- return (b0 | (b1<<8) | (b2<<16) | (b3<<24));
- };
-
- virtual uint32_t read4high()
- {
- uint8_t b0, b1, b2, b3;
- b3 = static_cast<uint8_t >(*buf_ptr++);
- b2 = static_cast<uint8_t >(*buf_ptr++);
- b1 = static_cast<uint8_t >(*buf_ptr++);
- b0 = static_cast<uint8_t >(*buf_ptr++);
- return (b0 | (b1<<8) | (b2<<16) | (b3<<24));
- };
-
- virtual float readf()
- {
- uint8_t b0, b1, b2, b3;
- b0 = static_cast<uint8_t >(*buf_ptr++);
- b1 = static_cast<uint8_t >(*buf_ptr++);
- b2 = static_cast<uint8_t >(*buf_ptr++);
- b3 = static_cast<uint8_t >(*buf_ptr++);
- uint_float uif;
- uif.i = (b0 | (b1<<8) | (b2<<16) | (b3<<24));
- return uif.f;
- };
-
- void read(uint8_t *b, int len) {
- memcpy(b, buf_ptr, len);
- buf_ptr += len;
- };
-
- virtual void write1(unsigned int val)
- {
- *buf_ptr++ = val & 0xff;
- };
-
- virtual void write2(uint16_t val)
- {
- *buf_ptr++ = val & 0xff;
- *buf_ptr++ = (val>>8) & 0xff;
- };
-
- virtual void write2high(uint16_t val)
- {
- *buf_ptr++ = (val>>8) & 0xff;
- *buf_ptr++ = val & 0xff;
- };
-
-
- virtual void write4(uint32_t val)
- {
- *buf_ptr++ = val & 0xff;
- *buf_ptr++ = (val>>8) & 0xff;
- *buf_ptr++ = (val>>16)&0xff;
- *buf_ptr++ = (val>>24)&0xff;
- };
-
- virtual void write4high(uint32_t val)
- {
- *buf_ptr++ = (val>>24)&0xff;
- *buf_ptr++ = (val>>16)&0xff;
- *buf_ptr++ = (val>>8) & 0xff;
- *buf_ptr++ = val & 0xff;
- };
-
- virtual void writef(float val)
- {
- uint_float uif;
- uif.f = val;
- *buf_ptr++ = uif.i & 0xff;
- *buf_ptr++ = (uif.i>>8) & 0xff;
- *buf_ptr++ = (uif.i>>16)&0xff;
- *buf_ptr++ = (uif.i>>24)&0xff;
- };
-
- virtual void write(uint8_t *b, int32_t len)
- {
- memcpy(buf_ptr, b, len);
- buf_ptr += len;
- };
-
- virtual void seek(unsigned int pos) { buf_ptr = const_cast<uint8_t *>(buf)+pos; };
-
- virtual void skip(int pos) { buf_ptr += pos; };
-
- virtual unsigned int getSize() { return size; };
-
- virtual unsigned int getPos() { return (buf_ptr-buf); };
-
- uint8_t *getPtr() { return buf_ptr; };
-};
-
-
-#endif
--- a/Game/src/midi/win_midiout.cpp
+++ /dev/null
@@ -1,1287 +1,0 @@
-/*
-Copyright (C) 2000, 2001, 2002 Ryan Nunn
-
-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
-aint32_t with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#if (__GNUG__ >= 2) && (!defined WIN32)
-# pragma interface
-#endif
-
-//Windows-specific code
-#ifdef WIN32
-
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-
-// These will prevent inclusion of mmsystem sections
-#define MMNODRV // Installable driver support
-#define MMNOSOUND // Sound support
-#define MMNOWAVE // Waveform support
-#define MMNOAUX // Auxiliary audio support
-#define MMNOMIXER // Mixer support
-#define MMNOTIMER // Timer support
-#define MMNOJOY // Joystick support
-#define MMNOMCI // MCI support
-#define MMNOMMIO // Multimedia file I/O support
-
-#include <windows.h>
-#include <mmsystem.h>
-#include <winbase.h>
-
-#include <string>
-#include <iostream>
-#include <cstdio>
-#include <cstdlib>
-#include <cstdarg>
-#include <cstring>
-#include <cassert>
-
-#include "win_midiout.h"
-#include "SDL_mixer.h"
-
-#define W32MO_THREAD_COM_READY 0
-#define W32MO_THREAD_COM_PLAY 1
-#define W32MO_THREAD_COM_STOP 2
-#define W32MO_THREAD_COM_INIT 3
-#define W32MO_THREAD_COM_INIT_FAILED 4
-#define W32MO_THREAD_COM_EXIT -1
-
-const unsigned short Windows_MidiOut::centre_value = 0x2000;
-const uint8_t Windows_MidiOut::fine_value = centre_value & 127;
-const uint8_t Windows_MidiOut::coarse_value = centre_value >> 7;
-const unsigned short Windows_MidiOut::combined_value = (coarse_value << 8) | fine_value;
-
-#define MUSIC_STATUS_IDLE 0
-#define MUSIC_STATUS_PLAYING 1
-
-uint8_t nMusicState = MUSIC_STATUS_IDLE;
-
-Mix_Music *music;
-
-//#define DO_SMP_TEST
-
-#ifdef DO_SMP_TEST
-#define giveinfo() std::cerr << __FILE__ << ":" << __LINE__ << std::endl; std::cerr.flush();
-#else
-#define giveinfo()
-#endif
-
-using std::string;
-using std::cout;
-using std::cerr;
-using std::endl;
-
-
-Windows_MidiOut::Windows_MidiOut() :
-dev_num(-1),
-new_volume(-1)
-{
- giveinfo();
- InterlockedExchange (&playing, false);
- InterlockedExchange (&s_playing, false);
- InterlockedExchange (&is_available, false);
- giveinfo();
- init_device();
- giveinfo();
-}
-
-Windows_MidiOut::~Windows_MidiOut()
-{
- giveinfo();
- if (!is_available) return;
-
- giveinfo();
- while (thread_com != W32MO_THREAD_COM_READY) Sleep (1);
-
- giveinfo();
- InterlockedExchange (&thread_com, W32MO_THREAD_COM_EXIT);
-
- giveinfo();
- int count = 0;
-
- giveinfo();
- while (count < 100)
- {
- giveinfo();
- DWORD code;
- GetExitCodeThread (thread_handle, &code);
-
- giveinfo();
- // Wait 1 MS before trying again
- if (code == STILL_ACTIVE) Sleep (10);
- else break;
- giveinfo();
-
- count++;
- }
-
- // We waited a second and it still didn't terminate
- giveinfo();
- if (count == 100 && is_available)
- TerminateThread (thread_handle, 1);
-
- giveinfo();
- InterlockedExchange (&is_available, false);
- giveinfo();
-}
-
-void Windows_MidiOut::init_device()
-{
- string s;
-
- // Opened, lets open the thread
- giveinfo();
- InterlockedExchange (&thread_com, W32MO_THREAD_COM_INIT);
-
- // Get Win32 Midi Device num
- dev_num = get_MusicDevice();//0;//MidiDevice;//0;//-1;
-
- giveinfo();
- thread_handle = (HANDLE*) CreateThread (NULL, 0, thread_start, this, 0, &thread_id);
-
- giveinfo();
- while (thread_com == W32MO_THREAD_COM_INIT) Sleep (1);
-
- giveinfo();
- if (thread_com == W32MO_THREAD_COM_INIT_FAILED) cerr << "Failure to initialize midi playing thread" << endl;
- giveinfo();
-}
-
-DWORD __stdcall Windows_MidiOut::thread_start(void *data)
-{
- giveinfo();
- Windows_MidiOut *ptr=static_cast<Windows_MidiOut *>(data);
- giveinfo();
- return ptr->thread_main();
-}
-
-DWORD Windows_MidiOut::thread_main()
-{
- int i;
- thread_data = NULL;
- giveinfo();
- InterlockedExchange (&playing, false);
- InterlockedExchange (&s_playing, false);
-
- giveinfo();
-
- // List all the midi devices.
- MIDIOUTCAPS caps;
- int32_t dev_count = (signed long) midiOutGetNumDevs();
- std::cout << dev_count << " Midi Devices Detected" << endl;
- std::cout << "Listing midi devices:" << endl;
-
- for (i = -1; i < dev_count; i++)
- {
- midiOutGetDevCaps ((UINT) i, &caps, sizeof(caps));
- std::cout << i << ": " << caps.szPname << endl;
- }
-
- if (dev_num < -1 || dev_num >= dev_count)
- {
- std::cerr << "Warning Midi device in config is out of range." << endl;
- dev_num = -1;
- }
- midiOutGetDevCaps ((UINT) dev_num, &caps, sizeof(caps));
- std::cout << "Using device " << dev_num << ": "<< caps.szPname << endl;
-
- UINT mmsys_err = midiOutOpen (&midi_port, dev_num, 0, 0, 0);
-
- giveinfo();
- if (mmsys_err != MMSYSERR_NOERROR)
- {
- char buf[512];
-
- giveinfo();
- midiOutGetErrorText(mmsys_err, buf, 512);
- cerr << "Unable to open device: " << buf << endl;
- giveinfo();
- InterlockedExchange (&thread_com, W32MO_THREAD_COM_INIT_FAILED);
- giveinfo();
- return 1;
- }
- giveinfo();
- InterlockedExchange (&is_available, true);
-
-// SetThreadPriority (thread_handle, THREAD_PRIORITY_HIGHEST);
- giveinfo();
- SetThreadPriority (thread_handle, THREAD_PRIORITY_TIME_CRITICAL);
-
- giveinfo();
- InterlockedExchange (&thread_com, W32MO_THREAD_COM_READY);
- InterlockedExchange (&sfx_com, W32MO_THREAD_COM_READY);
-
- giveinfo();
- thread_play();
- giveinfo();
-
- giveinfo();
- Sleep(100);
- midiOutClose (midi_port);
- Sleep(100);
- giveinfo();
- giveinfo();
- return 0;
-}
-
-void Windows_MidiOut::thread_play ()
-{
- int repeat = false;
- uint32_t aim = 0;
- int32_t diff = 0;
- uint32_t last_tick = 0;
- XMIDIEventList *evntlist = NULL;
- midi_event *event = NULL;
- NoteStack notes_on;
- midi_event *note = NULL;
-
- //
- // Xmidi Looping
- //
-
- // The for loop event
- midi_event *loop_event[XMIDI_MAX_FOR_LOOP_COUNT];
-
- // The amount of times we have left that we can loop
- int loop_count[XMIDI_MAX_FOR_LOOP_COUNT];
-
- // The level of the loop we are currently in
- int loop_num = -1;
-
- giveinfo();
-
- int s_track = 0;
- uint32_t s_aim = 0;
- int32_t s_diff = 0;
- uint32_t s_last_tick = 0;
- NoteStack s_notes_on;
- XMIDIEventList *s_evntlist = NULL;
- midi_event *s_event = NULL;
-
- giveinfo();
-
- vol_multi = 0xFF;
-
- // Play while there isn't a message waiting
- while (1)
- {
- if (thread_com == W32MO_THREAD_COM_EXIT && !playing && !s_playing) break;
-
- // Volume settings
- if (new_volume != -1) {
- vol_multi = new_volume;
- new_volume = -1;
-
- for (int i = 0; i < 16; i++) {
- uint32_t message = i;
- message |= MIDI_STATUS_CONTROLLER << 4;
- message |= 7 << 8;
- message |= ((volumes[i] * vol_multi)/0xFF)<<16;
- midiOutShortMsg (midi_port, message);
- }
- }
-
- if (thread_com == W32MO_THREAD_COM_STOP)
- {
- giveinfo();
- InterlockedExchange (&playing, FALSE);
- InterlockedExchange (&thread_com, W32MO_THREAD_COM_READY);
-
- // Handle note off's here
- while (note = notes_on.Pop())
- midiOutShortMsg (midi_port, note->status + (note->data[0] << 8));
-
- giveinfo();
- // Clean up
- for (int i = 0; i < 16; i++) reset_channel (i);
-
- midiOutReset (midi_port);
- giveinfo();
- if (evntlist) evntlist->DecerementCounter();
- giveinfo();
- evntlist = NULL;
- event = NULL;
- giveinfo();
-
- // If stop was requested, we are ready to receive another song
-
- loop_num = -1;
-
- wmoInitClock ();
- last_tick = 0;
- }
-
- // Handle note off's here
- while (note = notes_on.PopTime(wmoGetRealTime()))
- midiOutShortMsg (midi_port, note->status + (note->data[0] << 8));
-
- while (note = s_notes_on.PopTime(wmoGetRealTime()))
- midiOutShortMsg (midi_port, note->status + (note->data[0] << 8));
-
- while (event && thread_com != W32MO_THREAD_COM_STOP)
- {
- aim = (event->time-last_tick)*50;
- diff = aim - wmoGetTime ();
-
- if (diff > 0) break;
-
- last_tick = event->time;
- wmoAddOffset(aim);
-
- // XMIDI For Loop
- if ((event->status >> 4) == MIDI_STATUS_CONTROLLER && event->data[0] == XMIDI_CONTROLLER_FOR_LOOP)
- {
- if (loop_num < XMIDI_MAX_FOR_LOOP_COUNT) loop_num++;
-
- loop_count[loop_num] = event->data[1];
- loop_event[loop_num] = event;
-
- } // XMIDI Next/Break
- else if ((event->status >> 4) == MIDI_STATUS_CONTROLLER && event->data[0] == XMIDI_CONTROLLER_NEXT_BREAK)
- {
- if (loop_num != -1)
- {
- if (event->data[1] < 64)
- {
- loop_num--;
- }
- }
- event = NULL;
-
- } // XMIDI Callback Trigger
- else if ((event->status >> 4) == MIDI_STATUS_CONTROLLER && event->data[0] == XMIDI_CONTROLLER_CALLBACK_TRIG)
- {
- // TODO
- } // Not SysEx
- else if (event->status < 0xF0)
- {
- unsigned int type = event->status >> 4;
- uint32_t data = event->data[0] | (event->data[1] << 8);
-
- // Channel volume
- if (type == MIDI_STATUS_CONTROLLER && event->data[0] == 0x7) {
- volumes[event->status &0xF] = event->data[1];
- data = event->data[0] | (((event->data[1] * vol_multi)/0xFF)<<8);
- }
-
- if ((type != MIDI_STATUS_NOTE_ON || event->data[1]) && type != MIDI_STATUS_NOTE_OFF) {
- if (type == MIDI_STATUS_NOTE_ON) {
- notes_on.Remove(event);
- notes_on.Push (event, event->duration * 50 + wmoGetStart());
- }
-
- midiOutShortMsg (midi_port, event->status | (data<<8));
- }
- }
-
- if (event) event = event->next;
-
- if (!event || thread_com != W32MO_THREAD_COM_READY)
- {
- bool clean = !repeat || (thread_com != W32MO_THREAD_COM_READY) || last_tick == 0;
-
- if (clean)
- {
- InterlockedExchange (&playing, FALSE);
- if (thread_com == W32MO_THREAD_COM_STOP)
- InterlockedExchange (&thread_com, W32MO_THREAD_COM_READY);
-
- // Handle note off's here
- while (note = notes_on.Pop())
- midiOutShortMsg (midi_port, note->status + (note->data[0] << 8));
-
- // Clean up
- for (int i = 0; i < 16; i++) reset_channel (i);
- midiOutReset (midi_port);
- if (evntlist) evntlist->DecerementCounter();
- evntlist = NULL;
- event = NULL;
-
- loop_num = -1;
- wmoInitClock ();
- }
-
- last_tick = 0;
-
- if (evntlist)
- {
- if (loop_num == -1) event = evntlist->events;
- else
- {
- event = loop_event[loop_num]->next;
- last_tick = loop_event[loop_num]->time;
-
- if (loop_count[loop_num])
- if (!--loop_count[loop_num])
- loop_num--;
- }
- }
- }
- }
-
-
- // Got issued a music play command
- // set up the music playing routine
- if (thread_com == W32MO_THREAD_COM_PLAY)
- {
- // Handle note off's here
- while (note = notes_on.Pop())
- midiOutShortMsg (midi_port, note->status + (note->data[0] << 8));
-
- // Manual Reset since I don't trust midiOutReset()
- giveinfo();
- for (int i = 0; i < 16; i++) reset_channel (i);
- midiOutReset (midi_port);
-
- if (evntlist) evntlist->DecerementCounter();
- evntlist = NULL;
- event = NULL;
- InterlockedExchange (&playing, FALSE);
-
- // Make sure that the data exists
- giveinfo();
- while (!thread_data) Sleep(1);
-
- giveinfo();
- evntlist = thread_data->list;
- repeat = thread_data->repeat;
-
- giveinfo();
- InterlockedExchange ((LONG*) &thread_data, (LONG) NULL);
- giveinfo();
- InterlockedExchange (&thread_com, W32MO_THREAD_COM_READY);
-
- giveinfo();
- if (evntlist) event = evntlist->events;
- else event = 0;
-
- giveinfo();
- last_tick = 0;
-
- giveinfo();
- wmoInitClock ();
-
- // Reset XMIDI Looping
- loop_num = -1;
-
- giveinfo();
- InterlockedExchange (&playing, true);
- }
-
- if (s_event)
- {
- s_aim = (s_event->time-s_last_tick)*50;
- s_diff = s_aim - wmoGetSFXTime ();
- }
- else
- s_diff = 1;
-
- if (s_diff <= 0)
- {
- s_last_tick = s_event->time;
- wmoAddSFXOffset(s_aim);
-
- // Not SysEx
- if ((s_event->status >> 4) != MIDI_STATUS_SYSEX)
- {
- int type = s_event->status >> 4;
-
- if ((type != MIDI_STATUS_NOTE_ON || s_event->data[1]) && type != MIDI_STATUS_NOTE_OFF) {
- if (type == MIDI_STATUS_NOTE_ON) {
- s_notes_on.Remove(s_event);
- s_notes_on.Push (s_event, s_event->duration * 50 + wmoGetSFXStart());
- }
-
- midiOutShortMsg (midi_port, s_event->status + (s_event->data[0] << 8) + (s_event->data[1] << 16));
- }
- s_track |= 1 << (s_event->status & 0xF);
- }
-
- s_event = s_event->next;
- }
- if (s_evntlist && (!s_event || thread_com == W32MO_THREAD_COM_EXIT || sfx_com != W32MO_THREAD_COM_READY))
- {
- // Play all the remaining note offs
- while (note = s_notes_on.Pop())
- midiOutShortMsg (midi_port, note->status + (note->data[0] << 8));
-
- // Also reset the played tracks
- for (int i = 0; i < 16; i++) if ((s_track >> i)&1) reset_channel (i);
-
- s_evntlist->DecerementCounter();
- s_evntlist = NULL;
- s_event = NULL;
- InterlockedExchange (&s_playing, false);
- if (sfx_com != W32MO_THREAD_COM_PLAY) InterlockedExchange (&sfx_com, W32MO_THREAD_COM_READY);
- }
-
- // Got issued a sound effect play command
- // set up the sound effect playing routine
- if (!s_evntlist && sfx_com == W32MO_THREAD_COM_PLAY)
- {
- giveinfo();
- cout << "Play sfx command" << endl;
-
- // Play all the remaining note offs
- while (note = s_notes_on.Pop())
- midiOutShortMsg (midi_port, note->status + (note->data[0] << 8));
-
- // Make sure that the data exists
- while (!sfx_data) Sleep(1);
-
- giveinfo();
- s_evntlist = sfx_data->list;
-
- giveinfo();
- InterlockedExchange ((LONG*) &sfx_data, (LONG) NULL);
- InterlockedExchange (&sfx_com, W32MO_THREAD_COM_READY);
- giveinfo();
-
- if (s_evntlist) s_event = s_evntlist->events;
- else s_event = 0;
-
- giveinfo();
-
- s_last_tick = 0;
-
- giveinfo();
- wmoInitSFXClock ();
-
- giveinfo();
- InterlockedExchange (&s_playing, true);
-
- giveinfo();
- // Reset thet track counter
- s_track = 0;
- }
-
- if (event)
- {
- aim = (event->time-last_tick)*50;
- diff = aim - wmoGetTime ();
- }
- else
- diff = 6;
-
- if (s_event)
- {
- s_aim = (s_event->time-s_last_tick)*50;
- s_diff = s_aim - wmoGetSFXTime ();
- }
- else
- s_diff = 6;
-
- //std::cout << sfx_com << endl;
-
- if (diff > 5 && s_diff > 5) Sleep (1);
- }
- // Handle note off's here
- while (note = notes_on.Pop())
- midiOutShortMsg (midi_port, note->status + (note->data[0] << 8));
-
- // Play all the remaining note offs
- while (note = s_notes_on.PopTime(wmoGetRealTime()))
- midiOutShortMsg (midi_port, note->status + (note->data[0] << 8));
-
- if (evntlist) evntlist->DecerementCounter();
- evntlist = NULL;
- if (s_evntlist) s_evntlist->DecerementCounter();
- s_evntlist = NULL;
- for (int i = 0; i < 16; i++) reset_channel (i);
- midiOutReset (midi_port);
- InterlockedExchange (&new_volume, -1);
-}
-
-void Windows_MidiOut::reset_channel (int i)
-{
- // Pitch Wheel
- midiOutShortMsg (midi_port, i | (MIDI_STATUS_PITCH_WHEEL << 4) | (combined_value << 8));
-
- // All controllers off
- midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (121 << 8));
-
- // All notes off
- midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (123 << 8));
-
- // Bank Select
- midiOutShortMsg (midi_port, i | (MIDI_STATUS_PROG_CHANGE << 4) | (0 << 8));
- midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (0 << 8));
- midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (32 << 8));
-
- // Modulation Wheel
- midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (1 << 8) | (coarse_value << 16));
- midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (33 << 8) | (fine_value << 16));
-
- // Volume
- volumes[i] = coarse_value;
- midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (7 << 8) | (((coarse_value*vol_multi)/0xFF) << 16));
- midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (39 << 8) | (fine_value << 16));
-
- // Pan
- midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (8 << 8) | (coarse_value << 16));
- midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (40 << 8) | (fine_value << 16));
-
- // Balance
- midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (10 << 8) | (coarse_value << 16));
- midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (42 << 8) | (fine_value << 16));
-
- // Effects (Reverb)
- midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (91 << 8));
-
- // Chorus
- midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (93 << 8));
-}
-
-void Windows_MidiOut::start_track (XMIDIEventList *xmidi, bool repeat)
-{
- giveinfo();
- if (!is_available)
- init_device();
-
- giveinfo();
- if (!is_available)
- return;
-
- giveinfo();
- while (thread_com != W32MO_THREAD_COM_READY) Sleep (1);
-
- giveinfo();
- xmidi->IncerementCounter();
- data.list = xmidi;
- data.repeat = repeat;
-// xmidi->Write("winmidi_out.mid");
-
- giveinfo();
- InterlockedExchange ((LONG*) &thread_data, (LONG) &data);
- giveinfo();
- InterlockedExchange (&thread_com, W32MO_THREAD_COM_PLAY);
- giveinfo();
-}
-
-void Windows_MidiOut::start_sfx(XMIDIEventList *xmidi)
-{
- giveinfo();
- if (!is_available)
- init_device();
-
- giveinfo();
- if (!is_available)
- return;
-
- giveinfo();
- while (sfx_com != W32MO_THREAD_COM_READY) Sleep (1);
-
- giveinfo();
- xmidi->IncerementCounter();
- sdata.list = xmidi;
- sdata.repeat;
-
- giveinfo();
- InterlockedExchange ((LONG*) &sfx_data, (LONG) &sdata);
- giveinfo();
- InterlockedExchange (&sfx_com, W32MO_THREAD_COM_PLAY);
- giveinfo();
-}
-
-
-void Windows_MidiOut::stop_track(void)
-{
- giveinfo();
- if (!is_available)
- return;
-
- giveinfo();
- if (!playing) return;
-
- giveinfo();
- while (thread_com != W32MO_THREAD_COM_READY) Sleep (1);
- giveinfo();
- InterlockedExchange (&thread_com, W32MO_THREAD_COM_STOP);
- giveinfo();
- while (thread_com != W32MO_THREAD_COM_READY) Sleep (1);
- giveinfo();
-}
-
-void Windows_MidiOut::stop_sfx(void)
-{
- giveinfo();
- if (!is_available)
- return;
-
- giveinfo();
- if (!s_playing) return;
-
- giveinfo();
- while (sfx_com != W32MO_THREAD_COM_READY) Sleep (1);
- giveinfo();
- InterlockedExchange (&sfx_com, W32MO_THREAD_COM_STOP);
- giveinfo();
-}
-
-bool Windows_MidiOut::is_playing(void)
-{
- giveinfo();
- return playing!=0;
-}
-
-const char *Windows_MidiOut::copyright(void)
-{
- giveinfo();
- return "Internal Win32 Midiout Midi Player for Pentagram. Version 1.2a";
-}
-
-//
-// PSMDEX - Pentagram Streaming Midi Driver Extensions
-//
-
-int Windows_MidiOut::max_streams()
-{
- return 1;
-}
-
-void Windows_MidiOut::start_stream(int str_num, XMIDIEventList *eventlist, bool repeat, bool activate, int vol)
-{
- stop_track();
- set_volume(0, vol);
- start_track(eventlist, repeat);
-}
-
-void Windows_MidiOut::activate_stream(int str_num)
-{
-
-}
-
-void Windows_MidiOut::stop_stream(int str_num)
-{
- stop_track();
-}
-
-void Windows_MidiOut::set_volume(int str_num, int level)
-{
- if (!is_available) return;
-
- while (new_volume != -1) Sleep (1);
- InterlockedExchange (&new_volume, level);
-}
-
-bool Windows_MidiOut::is_playing(int str_num)
-{
- return is_playing();
-}
-
-int Windows_MidiOut::get_active()
-{
- return 0;
-}
-
-extern "C"
-{
- #include "../duke3d.h"
-
- int get_MusicDevice()
- {
- return MusicDevice;
- }
-}
-
-extern "C"
-{
-
-// The music functions...
-
-#include "../duke3d.h"
-#include "cache1d.h"
-
-static char warningMessage[80];
-static char errorMessage[80];
-
-char *MUSIC_ErrorString(int ErrorNumber)
-{
- switch (ErrorNumber)
- {
- case MUSIC_Warning:
- return(warningMessage);
-
- case MUSIC_Error:
- return(errorMessage);
-
- case MUSIC_Ok:
- return("OK; no error.");
-
- case MUSIC_ASSVersion:
- return("Incorrect sound library version.");
-
- case MUSIC_SoundCardError:
- return("General sound card error.");
-
- case MUSIC_InvalidCard:
- return("Invalid sound card.");
-
- case MUSIC_MidiError:
- return("MIDI error.");
-
- case MUSIC_MPU401Error:
- return("MPU401 error.");
-
- case MUSIC_TaskManError:
- return("Task Manager error.");
-
- case MUSIC_FMNotDetected:
- return("FM not detected error.");
-
- case MUSIC_DPMI_Error:
- return("DPMI error.");
-
- default:
- return("Unknown error.");
- } // switch
-
- assert(0); // shouldn't hit this point.
- return(NULL);
-} // MUSIC_ErrorString
-
-
-static int music_initialized = 0, ext_music_initialized = 1;
-static int music_context = 0;
-static int music_loopflag = MUSIC_PlayOnce;
-static Windows_MidiOut *midi_device = NULL;
-
-extern void musdebug(const char *fmt, ...);
-extern void init_debugging(void);
-extern void setWarningMessage(const char *msg);
-extern void setErrorMessage(const char *msg);
-extern int MUSIC_ErrorCode;
-#define __FX_TRUE (1 == 1)
-#define __FX_FALSE (!__FX_TRUE)
-
-#pragma message (" The win_midi code is temp until the SDL midi code functions properly ")
-
-#pragma message (" STUBBED musdebug ")
-void musdebug(const char *fmt, ...)
-{
-#if 0
- va_list ap;
-
- if (false)
- {
- fprintf(debug_file, "DUKEMUS: ");
- va_start(ap, fmt);
- vfprintf(debug_file, fmt, ap);
- va_end(ap);
- fprintf(debug_file, "\n");
- fflush(debug_file);
- } // if
-#endif
-} // snddebug
-
-#pragma message (" STUBBED setErrorMessage ")
-static void setErrorMessage(const char *msg)
-{
-#if 0
- strncpy(errorMessage, msg, sizeof (errorMessage));
- // strncpy() doesn't add the null uint8_t if there isn't room...
- errorMessage[sizeof (errorMessage) - 1] = '\0';
- snddebug("Error message set to [%s].", errorMessage);
-#endif
-} // setErrorMessage
-
-#pragma message (" STUBBED init_debugging ")
-static void init_debugging(void)
-{
-
-}
-
-
-int MUSIC_Init(int SoundCard, int Address)
-{
- init_debugging();
-
- musdebug("INIT! card=>%d, address=>%d...", SoundCard, Address);
-
- if (music_initialized)
- {
- setErrorMessage("Music system is already initialized.");
- return(MUSIC_Error);
- } // if
-
- music_initialized = 1;
-
- midi_device = new Windows_MidiOut();
-
- if(Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 1024)==-1) {
- printf("Mix_OpenAudio: %s\n", Mix_GetError());
- }
- else {
- ext_music_initialized = 1;
- }
-
-
- return(MUSIC_Ok);
-} // MUSIC_Init
-
-
-int MUSIC_Shutdown(void)
-{
- musdebug("shutting down sound subsystem.");
-
- if ((!music_initialized) && (!ext_music_initialized))
- {
- setErrorMessage("Music system is not currently initialized.");
- return(MUSIC_Error);
- } // if
-
- if(midi_device)
- delete midi_device;
- midi_device = 0;
- music_context = 0;
- music_initialized = 0;
- music_loopflag = MUSIC_PlayOnce;
-
- nMusicState = MUSIC_STATUS_IDLE;
-
- return(MUSIC_Ok);
-} // MUSIC_Shutdown
-
-
-void MUSIC_SetMaxFMMidiChannel(int channel)
-{
- musdebug("STUB ... MUSIC_SetMaxFMMidiChannel(%d).\n", channel);
-} // MUSIC_SetMaxFMMidiChannel
-
-
-void MUSIC_SetVolume(int volume)
-{
- if(midi_device)
- midi_device->set_volume(0,volume);
-
- if (ext_music_initialized == 1)
- Mix_VolumeMusic((int)(volume / 2));
-
-}
-
-void MUSIC_SetMidiChannelVolume(int channel, int volume)
-{
- musdebug("STUB ... MUSIC_SetMidiChannelVolume(%d, %d).\n", channel, volume);
-} // MUSIC_SetMidiChannelVolume
-
-
-void MUSIC_ResetMidiChannelVolumes(void)
-{
- musdebug("STUB ... MUSIC_ResetMidiChannelVolumes().\n");
-} // MUSIC_ResetMidiChannelVolumes
-
-
-int MUSIC_GetVolume(void)
-{
- if(midi_device)
- return midi_device->vol_multi;
- else
- return 0;
-} // MUSIC_GetVolume
-
-
-void MUSIC_SetLoopFlag(int loopflag)
-{
- music_loopflag = loopflag;
-} // MUSIC_SetLoopFlag
-
-
-int MUSIC_SongPlaying(void)
-{
- if (ext_music_initialized)
- {
- return((Mix_PlayingMusic()) ? __FX_TRUE : __FX_FALSE);
- }
- else
- {
- if(midi_device)
- return midi_device->is_playing()?__FX_TRUE : __FX_FALSE;
- else
- return __FX_FALSE;
- }
-
-} // MUSIC_SongPlaying
-
-
-void MUSIC_Continue(void)
-{
- if (Mix_PausedMusic())
- Mix_ResumeMusic();
- //else if (music_songdata)
- // MUSIC_PlaySong(music_songdata, MUSIC_PlayOnce);
-} // MUSIC_Continue
-
-
-void MUSIC_Pause(void)
-{
- Mix_PauseMusic();
-} // MUSIC_Pause
-
-
-int MUSIC_StopSong(void)
-{
- if ( (Mix_PlayingMusic()) || (Mix_PausedMusic()) )
- {
- Mix_HaltMusic();
-
- if (music) Mix_FreeMusic(music);
-
- nMusicState = MUSIC_STATUS_IDLE;
- }
-
- if(midi_device) midi_device->stop_stream(0);
-
- return(MUSIC_Ok);
-} // MUSIC_StopSong
-
-
-int MUSIC_PlaySong(char *songFilename, int loopflag)
-{
- int32_t GRPFileHandle;
- SDL_RWops *rw;
-
- MUSIC_StopSong();
-
- //music_songdata = song;
-
- // !!! FIXME: This could be a problem...SDL/SDL_mixer wants a RWops, which
- // !!! FIXME: is an i/o abstraction. Since we already have the MIDI data
- // !!! FIXME: in memory, we fake it with a memory-based RWops. None of
- // !!! FIXME: this is a problem, except the RWops wants to know how big
- // !!! FIXME: its memory block is (so it can do things like seek on an
- // !!! FIXME: offset from the end of the block), and since we don't have
- // !!! FIXME: this information, we have to give it SOMETHING.
-
-
- if(midi_device)
- midi_device->stop_stream(0);
-
- BufferDataSource mid_data((uint8_t *)song, 1024 * 1024);
- XMIDI midfile(&mid_data, XMIDI_CONVERT_EMIDI_GM);
- XMIDIEventList *eventlist = midfile.GetEventList(0);
- if (eventlist)
- {
- if(midi_device)
- midi_device->start_track(eventlist, loopflag?true:false);
- }
-
-//STUBBED("Need to use PlaySongROTT. :(");
-
- return(MUSIC_Ok);
-} // MUSIC_PlaySong
-
-int MUSIC_PlayExtSong(char *fn)
-{
- MUSIC_StopSong();
-
- if(midi_device)
- midi_device->stop_stream(0);
-
- music = Mix_LoadMUS(fn);
- if(!music)
- {
- printf("Mix_LoadMUS(\"%s\"): %s\n", fn, Mix_GetError());
- nMusicState = MUSIC_STATUS_IDLE;
- }
- else
- {
-
- if(Mix_PlayMusic(music, -1)==-1)
- {
- printf("Mix_PlayMusic: %s\n", Mix_GetError());
- nMusicState = MUSIC_STATUS_IDLE;
- }
- else
- {
- nMusicState = MUSIC_STATUS_PLAYING;
- }
- }
-
- return(MUSIC_Ok);
-
-}
-
-
-extern uint8_t ApogeePath[256];
-
-static void CheckAndPlayMusicType(const char * szName, const char * szType)
-{
-
- char fpath[1024] = {'\0'};
-
- // Is this a TC?
- if(game_dir[0] != '\0')
- {
-
- sprintf(fpath, "%s\\%s%s", game_dir, szName, szType);
- }
- else
- {
- // FIX_00010: Hi resolution tunes (*.ogg files) are now first searched in .\tunes\
- // and then searched in the main folder. Allows a better separation of files
- // OGG tunes are NOT required. They are only used if found else normal
- // MIDI files are used by default for music
-
- sprintf(fpath, "%s\\%s%s", HIRESMUSICPATH, szName, szType);
- if (!SafeFileExists(fpath))
- sprintf(fpath, "%s%s", szName, szType);
- }
-
- // Play MP3 file if available
- if (nMusicState == MUSIC_STATUS_IDLE)
- {
- //If it exists let's play it.
- if (SafeFileExists(fpath))
- {
- MUSIC_PlayExtSong(fpath);
- }
- }
-}
-
-// Duke3D-specific. --ryan.
-void PlayMusic(char *fn)
-{
- short fp;
- int32_t l;
- char *cfn;
- char *buffer;
- uint8_t fpath[19] = {'\0'};
-
- cfn = fn;
-
- //GetOnlyNameOfFile(cfn);
- buffer = strtok(cfn, ".");
-
- CheckAndPlayMusicType(buffer, ".ogg");
- CheckAndPlayMusicType(buffer, ".mp3");
- CheckAndPlayMusicType(buffer, ".mod");
- CheckAndPlayMusicType(buffer, ".s3m");
- CheckAndPlayMusicType(buffer, ".it");
- CheckAndPlayMusicType(buffer, ".xm");
- CheckAndPlayMusicType(buffer, ".wav");
-
- // else fall back to the midis.
- if (nMusicState == MUSIC_STATUS_IDLE)
- {
- if(MusicToggle == 0) return;
- if(MusicDevice == NumSoundCards) return;
- if(eightytwofifty && numplayers > 1) return;
-
- fp = kopen4load(fn,0);
-
- if(fp == -1) return;
-
- l = kfilelength( fp );
- if(l >= 72000)
- {
- kclose(fp);
- return;
- }
-
- kread( fp, MusicPtr, l);
- kclose( fp );
- MUSIC_PlaySong( (uint8_t *)MusicPtr, MUSIC_LoopSong );
- }
-}
-
-
-void MUSIC_SetContext(int context)
-{
- musdebug("STUB ... MUSIC_SetContext().\n");
- music_context = context;
-} // MUSIC_SetContext
-
-
-int MUSIC_GetContext(void)
-{
- return(music_context);
-} // MUSIC_GetContext
-
-
-void MUSIC_SetSongTick(uint32_t PositionInTicks)
-{
- musdebug("STUB ... MUSIC_SetSongTick().\n");
-} // MUSIC_SetSongTick
-
-
-void MUSIC_SetSongTime(uint32_t milliseconds)
-{
- musdebug("STUB ... MUSIC_SetSongTime().\n");
-}// MUSIC_SetSongTime
-
-
-void MUSIC_SetSongPosition(int measure, int beat, int tick)
-{
- musdebug("STUB ... MUSIC_SetSongPosition().\n");
-} // MUSIC_SetSongPosition
-
-
-void MUSIC_GetSongPosition(songposition *pos)
-{
- musdebug("STUB ... MUSIC_GetSongPosition().\n");
-} // MUSIC_GetSongPosition
-
-
-void MUSIC_GetSongLength(songposition *pos)
-{
- musdebug("STUB ... MUSIC_GetSongLength().\n");
-} // MUSIC_GetSongLength
-
-
-int MUSIC_FadeVolume(int tovolume, int milliseconds)
-{
- // Mix_FadeOutMusic(milliseconds);
- return(MUSIC_Ok);
-} // MUSIC_FadeVolume
-
-
-int MUSIC_FadeActive(void)
-{
- // return((Mix_FadingMusic() == MIX_FADING_OUT) ? __FX_TRUE : __FX_FALSE);
- return __FX_FALSE;
-} // MUSIC_FadeActive
-
-
-void MUSIC_StopFade(void)
-{
- musdebug("STUB ... MUSIC_StopFade().\n");
-} // MUSIC_StopFade
-
-
-void MUSIC_RerouteMidiChannel(int channel, int cdecl ( *function )( int event, int c1, int c2 ))
-{
- musdebug("STUB ... MUSIC_RerouteMidiChannel().\n");
-} // MUSIC_RerouteMidiChannel
-
-
-void MUSIC_RegisterTimbreBank(uint8_t *timbres)
-{
- musdebug("STUB ... MUSIC_RegisterTimbreBank().\n");
-} // MUSIC_RegisterTimbreBank
-
-
-// end of fx_man.c ...
-
-}
-
-
-
-#endif
--- a/Game/src/midi/win_midiout.h
+++ /dev/null
@@ -1,159 +1,0 @@
-/*
-Copyright (C) 2000, 2001, 2002 Ryan Nunn
-
-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
-aint32_t with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#ifndef WIN_MIDIOUT_H
-#define WIN_MIDIOUT_H
-
-
-
-#if (__GNUG__ >= 2) && (!defined WIN32)
-# pragma interface
-#endif
-
-#ifdef WIN32
-
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-
-// These will prevent inclusion of mmsystem sections
-#define MMNODRV // Installable driver support
-#define MMNOSOUND // Sound support
-#define MMNOWAVE // Waveform support
-#define MMNOAUX // Auxiliary audio support
-#define MMNOMIXER // Mixer support
-#define MMNOTIMER // Timer support
-#define MMNOJOY // Joystick support
-#define MMNOMCI // MCI support
-#define MMNOMMIO // Multimedia file I/O support
-
-#include <windows.h>
-#include <mmsystem.h>
-#include "xmidi.h"
-
-#ifdef _WIN32
- #include "../../Engine/src/windows/inttypes.h"
- #define inline
-#else
- #include <inttypes.h>
-#endif
-
-class Windows_MidiOut
-{
-public:
- virtual void start_track(XMIDIEventList *, bool repeat);
- virtual void start_sfx(XMIDIEventList *);
- virtual void stop_track(void);
- virtual void stop_sfx(void);
- virtual bool is_playing(void);
- virtual const char *copyright(void);
-
- // PSMDEX - Pentagram Streaming Midi Driver Extensions
- virtual int max_streams();
- virtual void start_stream(int str_num, XMIDIEventList *, bool repeat, bool activate, int vol);
- virtual void activate_stream(int str_num);
- virtual void stop_stream(int str_num);
- virtual void set_volume(int str_num, int level);
- virtual bool is_playing(int str_num);
- virtual int get_active();
-
- Windows_MidiOut();
- virtual ~Windows_MidiOut();
-
-//private:
-
- struct mid_data {
- XMIDIEventList *list;
- bool repeat;
- };
-
- static const unsigned short centre_value;
- static const uint8_t fine_value;
- static const uint8_t coarse_value;
- static const unsigned short combined_value;
-
- signed int dev_num;
- HMIDIOUT midi_port;
-
- HANDLE *thread_handle;
- DWORD thread_id;
-
- // Thread communicatoins
- LONG is_available;
- LONG playing;
- LONG s_playing;
- LONG thread_com;
- LONG sfx_com;
-
- LONG new_volume;
- LONG volumes[16];
- LONG vol_multi;
-
- mid_data *thread_data;
- mid_data *sfx_data;
-
- mid_data data;
- mid_data sdata;
-
- // Methods
- static DWORD __stdcall thread_start(void *data);
- void init_device();
- DWORD thread_main();
- void thread_play ();
- void reset_channel (int i);
-
- // Microsecond Clock
- uint32_t start;
- uint32_t sfx_start;
-
- inline void wmoInitClock ()
- { start = GetTickCount()*6; }
-
- inline void wmoAddOffset (uint32_t offset)
- { start += offset; }
-
- inline uint32_t wmoGetTime ()
- { return GetTickCount()*6 - start; }
-
- inline uint32_t wmoGetStart ()
- { return start; }
-
- inline uint32_t wmoGetRealTime ()
- { return GetTickCount()*6; }
-
- inline void wmoInitSFXClock ()
- { sfx_start = GetTickCount()*6; }
-
- inline void wmoAddSFXOffset (uint32_t offset)
- { sfx_start += offset; }
-
- inline uint32_t wmoGetSFXTime ()
- { return GetTickCount()*6 - sfx_start; }
-
- inline uint32_t wmoGetSFXStart ()
- { return sfx_start; }
-};
-
-#endif //WIN32
-
-extern "C"
-{
- int get_MusicDevice();
-}
-
-#endif //WIN_MIDIOUT_H
--- a/Game/src/midi/xmidi.cpp
+++ /dev/null
@@ -1,1567 +1,0 @@
-/*
- *
- * 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
- * aint32_t with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#ifndef ALPHA_LINUX_CXX
-# include <cassert>
-# include <cstdio>
-# include <cmath>
-# include <iostream>
-# include <cmath>
-#endif
-#include "xmidi.h"
-
-using std::cerr;
-using std::endl;
-using std::string;
-
-// Here's a bit of joy: WIN32 isn't SMP safe if we use operator new and delete.
-// On the other hand, nothing else is thread-safe if we use malloc()/free().
-// So, we wrap the implementations and use malloc()/calloc()/free() for WIN32, and
-// the C++ thread-safe allocator for other platforms.
-
-template<class T>
-inline T* Malloc(size_t num=1)
-{
-#ifdef WIN32
- return static_cast<T*>(malloc(num));
-#else
- return static_cast<T*>(::operator new(num));
-#endif
-}
-
-template<class T>
-inline T* Calloc(size_t num=1,size_t sz=0)
-{
- if(!sz)
- sz=sizeof(T);
-#ifdef WIN32
- return static_cast<T*>(calloc(num,sz));
-#else
- size_t total=sz*num;
- T *tmp=Malloc<T>(total);
- std::memset(tmp,0,total);
- return tmp;
-#endif
-}
-
-inline void Free(void *ptr)
-{
-#ifdef WIN32
- free(ptr);
-#else
- ::operator delete(ptr);
-#endif
-}
-
-// This is used to correct incorrect patch, vol and pan changes in midi files
-// The bias is just a value to used to work out if a vol and pan beint32_t with a
-// patch change. This is to ensure that the default state of a midi file is with
-// the tracks centred, unless the first patch change says otherwise.
-#define PATCH_VOL_PAN_BIAS 5
-
-
-// This is a default set of patches to convert from MT32 to GM
-// The index is the MT32 Patch nubmer and the value is the GM Patch
-// This is only suitable for music that doesn'tdo timbre changes
-// XMIDIs that contain Timbre changes will not convert properly
-const uint8_t XMIDI::mt32asgm[128] = {
- 0, // 0 Piano 1
- 1, // 1 Piano 2
- 2, // 2 Piano 3 (synth)
- 4, // 3 EPiano 1
- 4, // 4 EPiano 2
- 5, // 5 EPiano 3
- 5, // 6 EPiano 4
- 3, // 7 Honkytonk
- 16, // 8 Organ 1
- 17, // 9 Organ 2
- 18, // 10 Organ 3
- 16, // 11 Organ 4
- 19, // 12 Pipe Organ 1
- 19, // 13 Pipe Organ 2
- 19, // 14 Pipe Organ 3
- 21, // 15 Accordion
- 6, // 16 Harpsichord 1
- 6, // 17 Harpsichord 2
- 6, // 18 Harpsichord 3
- 7, // 19 Clavinet 1
- 7, // 20 Clavinet 2
- 7, // 21 Clavinet 3
- 8, // 22 Celesta 1
- 8, // 23 Celesta 2
- 62, // 24 Synthbrass 1 (62)
- 63, // 25 Synthbrass 2 (63)
- 62, // 26 Synthbrass 3 Bank 8
- 63, // 27 Synthbrass 4 Bank 8
- 38, // 28 Synthbass 1
- 39, // 29 Synthbass 2
- 38, // 30 Synthbass 3 Bank 8
- 39, // 31 Synthbass 4 Bank 8
- 88, // 32 Fantasy
- 90, // 33 Harmonic Pan - No equiv closest is polysynth(90) :(
- 52, // 34 Choral ?? Currently set to SynthVox(54). Should it be ChoirAhhs(52)???
- 92, // 35 Glass
- 97, // 36 Soundtrack
- 99, // 37 Atmosphere
- 14, // 38 Warmbell, sounds kind of like crystal(98) perhaps Tubular Bells(14) would be better. It is!
- 54, // 39 FunnyVox, sounds alot like Bagpipe(109) and Shania(111)
- 98, // 40 EchoBell, no real equiv, sounds like Crystal(98)
- 96, // 41 IceRain
- 68, // 42 Oboe 2001, no equiv, just patching it to normal oboe(68)
- 95, // 43 EchoPans, no equiv, setting to SweepPad
- 81, // 44 DoctorSolo Bank 8
- 87, // 45 SchoolDaze, no real equiv
- 112, // 46 Bell Singer
- 80, // 47 SquareWave
- 48, // 48 Strings 1
- 48, // 49 Strings 2 - should be 49
- 44, // 50 Strings 3 (Synth) - Experimental set to Tremollo Strings - should be 50
- 45, // 51 Pizzicato Strings
- 40, // 52 Violin 1
- 40, // 53 Violin 2 ? Viola
- 42, // 54 Cello 1
- 42, // 55 Cello 2
- 43, // 56 Contrabass
- 46, // 57 Harp 1
- 46, // 58 Harp 2
- 24, // 59 Guitar 1 (Nylon)
- 25, // 60 Guitar 2 (Steel)
- 26, // 61 Elec Guitar 1
- 27, // 62 Elec Guitar 2
- 104, // 63 Sitar
- 32, // 64 Acou Bass 1
- 32, // 65 Acou Bass 2
- 33, // 66 Elec Bass 1
- 34, // 67 Elec Bass 2
- 36, // 68 Slap Bass 1
- 37, // 69 Slap Bass 2
- 35, // 70 Fretless Bass 1
- 35, // 71 Fretless Bass 2
- 73, // 72 Flute 1
- 73, // 73 Flute 2
- 72, // 74 Piccolo 1
- 72, // 75 Piccolo 2
- 74, // 76 Recorder
- 75, // 77 Pan Pipes
- 64, // 78 Sax 1
- 65, // 79 Sax 2
- 66, // 80 Sax 3
- 67, // 81 Sax 4
- 71, // 82 Clarinet 1
- 71, // 83 Clarinet 2
- 68, // 84 Oboe
- 69, // 85 English Horn (Cor Anglais)
- 70, // 86 Bassoon
- 22, // 87 Harmonica
- 56, // 88 Trumpet 1
- 56, // 89 Trumpet 2
- 57, // 90 Trombone 1
- 57, // 91 Trombone 2
- 60, // 92 French Horn 1
- 60, // 93 French Horn 2
- 58, // 94 Tuba
- 61, // 95 Brass Section 1
- 61, // 96 Brass Section 2
- 11, // 97 Vibes 1
- 11, // 98 Vibes 2
- 99, // 99 Syn Mallet Bank 1
- 112, // 100 WindBell no real equiv Set to TinkleBell(112)
- 9, // 101 Glockenspiel
- 14, // 102 Tubular Bells
- 13, // 103 Xylophone
- 12, // 104 Marimba
- 107, // 105 Koto
- 111, // 106 Sho?? set to Shanai(111)
- 77, // 107 Shakauhachi
- 78, // 108 Whistle 1
- 78, // 109 Whistle 2
- 76, // 110 Bottle Blow
- 76, // 111 Breathpipe no real equiv set to bottle blow(76)
- 47, // 112 Timpani
- 117, // 113 Melodic Tom
- 116, // 114 Deap Snare no equiv, set to Taiko(116)
- 118, // 115 Electric Perc 1
- 118, // 116 Electric Perc 2
- 116, // 117 Taiko
- 115, // 118 Taiko Rim, no real equiv, set to Woodblock(115)
- 119, // 119 Cymbal, no real equiv, set to reverse cymbal(119)
- 115, // 120 Castanets, no real equiv, in GM set to Woodblock(115)
- 112, // 121 Triangle, no real equiv, set to TinkleBell(112)
- 55, // 122 Orchestral Hit
- 124, // 123 Telephone
- 123, // 124 BirdTweet
- 94, // 125 Big Notes Pad no equiv, set to halo pad (94)
- 98, // 126 Water Bell set to Crystal Pad(98)
- 121 // 127 Jungle Tune set to Breath Noise
-};
-
-// Same as above, except include patch changes
-// so GS instruments can be used
-const uint8_t XMIDI::mt32asgs[256] = {
- 0, 0, // 0 Piano 1
- 1, 0, // 1 Piano 2
- 2, 0, // 2 Piano 3 (synth)
- 4, 0, // 3 EPiano 1
- 4, 0, // 4 EPiano 2
- 5, 0, // 5 EPiano 3
- 5, 0, // 6 EPiano 4
- 3, 0, // 7 Honkytonk
- 16, 0, // 8 Organ 1
- 17, 0, // 9 Organ 2
- 18, 0, // 10 Organ 3
- 16, 0, // 11 Organ 4
- 19, 0, // 12 Pipe Organ 1
- 19, 0, // 13 Pipe Organ 2
- 19, 0, // 14 Pipe Organ 3
- 21, 0, // 15 Accordion
- 6, 0, // 16 Harpsichord 1
- 6, 0, // 17 Harpsichord 2
- 6, 0, // 18 Harpsichord 3
- 7, 0, // 19 Clavinet 1
- 7, 0, // 20 Clavinet 2
- 7, 0, // 21 Clavinet 3
- 8, 0, // 22 Celesta 1
- 8, 0, // 23 Celesta 2
- 62, 0, // 24 Synthbrass 1 (62)
- 63, 0, // 25 Synthbrass 2 (63)
- 62, 0, // 26 Synthbrass 3 Bank 8
- 63, 0, // 27 Synthbrass 4 Bank 8
- 38, 0, // 28 Synthbass 1
- 39, 0, // 29 Synthbass 2
- 38, 0, // 30 Synthbass 3 Bank 8
- 39, 0, // 31 Synthbass 4 Bank 8
- 88, 0, // 32 Fantasy
- 90, 0, // 33 Harmonic Pan - No equiv closest is polysynth(90) :(
- 52, 0, // 34 Choral ?? Currently set to SynthVox(54). Should it be ChoirAhhs(52)???
- 92, 0, // 35 Glass
- 97, 0, // 36 Soundtrack
- 99, 0, // 37 Atmosphere
- 14, 0, // 38 Warmbell, sounds kind of like crystal(98) perhaps Tubular Bells(14) would be better. It is!
- 54, 0, // 39 FunnyVox, sounds alot like Bagpipe(109) and Shania(111)
- 98, 0, // 40 EchoBell, no real equiv, sounds like Crystal(98)
- 96, 0, // 41 IceRain
- 68, 0, // 42 Oboe 2001, no equiv, just patching it to normal oboe(68)
- 95, 0, // 43 EchoPans, no equiv, setting to SweepPad
- 81, 0, // 44 DoctorSolo Bank 8
- 87, 0, // 45 SchoolDaze, no real equiv
- 112, 0, // 46 Bell Singer
- 80, 0, // 47 SquareWave
- 48, 0, // 48 Strings 1
- 48, 0, // 49 Strings 2 - should be 49
- 44, 0, // 50 Strings 3 (Synth) - Experimental set to Tremollo Strings - should be 50
- 45, 0, // 51 Pizzicato Strings
- 40, 0, // 52 Violin 1
- 40, 0, // 53 Violin 2 ? Viola
- 42, 0, // 54 Cello 1
- 42, 0, // 55 Cello 2
- 43, 0, // 56 Contrabass
- 46, 0, // 57 Harp 1
- 46, 0, // 58 Harp 2
- 24, 0, // 59 Guitar 1 (Nylon)
- 25, 0, // 60 Guitar 2 (Steel)
- 26, 0, // 61 Elec Guitar 1
- 27, 0, // 62 Elec Guitar 2
- 104, 0, // 63 Sitar
- 32, 0, // 64 Acou Bass 1
- 32, 0, // 65 Acou Bass 2
- 33, 0, // 66 Elec Bass 1
- 34, 0, // 67 Elec Bass 2
- 36, 0, // 68 Slap Bass 1
- 37, 0, // 69 Slap Bass 2
- 35, 0, // 70 Fretless Bass 1
- 35, 0, // 71 Fretless Bass 2
- 73, 0, // 72 Flute 1
- 73, 0, // 73 Flute 2
- 72, 0, // 74 Piccolo 1
- 72, 0, // 75 Piccolo 2
- 74, 0, // 76 Recorder
- 75, 0, // 77 Pan Pipes
- 64, 0, // 78 Sax 1
- 65, 0, // 79 Sax 2
- 66, 0, // 80 Sax 3
- 67, 0, // 81 Sax 4
- 71, 0, // 82 Clarinet 1
- 71, 0, // 83 Clarinet 2
- 68, 0, // 84 Oboe
- 69, 0, // 85 English Horn (Cor Anglais)
- 70, 0, // 86 Bassoon
- 22, 0, // 87 Harmonica
- 56, 0, // 88 Trumpet 1
- 56, 0, // 89 Trumpet 2
- 57, 0, // 90 Trombone 1
- 57, 0, // 91 Trombone 2
- 60, 0, // 92 French Horn 1
- 60, 0, // 93 French Horn 2
- 58, 0, // 94 Tuba
- 61, 0, // 95 Brass Section 1
- 61, 0, // 96 Brass Section 2
- 11, 0, // 97 Vibes 1
- 11, 0, // 98 Vibes 2
- 99, 0, // 99 Syn Mallet Bank 1
- 112, 0, // 100 WindBell no real equiv Set to TinkleBell(112)
- 9, 0, // 101 Glockenspiel
- 14, 0, // 102 Tubular Bells
- 13, 0, // 103 Xylophone
- 12, 0, // 104 Marimba
- 107, 0, // 105 Koto
- 111, 0, // 106 Sho?? set to Shanai(111)
- 77, 0, // 107 Shakauhachi
- 78, 0, // 108 Whistle 1
- 78, 0, // 109 Whistle 2
- 76, 0, // 110 Bottle Blow
- 76, 0, // 111 Breathpipe no real equiv set to bottle blow(76)
- 47, 0, // 112 Timpani
- 117, 0, // 113 Melodic Tom
- 116, 0, // 114 Deap Snare no equiv, set to Taiko(116)
- 118, 0, // 115 Electric Perc 1
- 118, 0, // 116 Electric Perc 2
- 116, 0, // 117 Taiko
- 115, 0, // 118 Taiko Rim, no real equiv, set to Woodblock(115)
- 119, 0, // 119 Cymbal, no real equiv, set to reverse cymbal(119)
- 115, 0, // 120 Castanets, no real equiv, in GM set to Woodblock(115)
- 112, 0, // 121 Triangle, no real equiv, set to TinkleBell(112)
- 55, 0, // 122 Orchestral Hit
- 124, 0, // 123 Telephone
- 123, 0, // 124 BirdTweet
- 94, 0, // 125 Big Notes Pad no equiv, set to halo pad (94)
- 98, 0, // 126 Water Bell set to Crystal Pad(98)
- 121, 0 // 127 Jungle Tune set to Breath Noise
-};
-
-// Constructor
-XMIDI::XMIDI(DataSource *source, int pconvert) : events(NULL),
- convert_type(pconvert), is_emidi(false),
- do_reverb(false), do_chorus(false)
-{
- if (convert_type == XMIDI_CONVERT_EMIDI_GM)
- {
- is_emidi = true;
- convert_type = XMIDI_CONVERT_NOCONVERSION;
- }
-
- memset(bank127,0,sizeof(bank127));
-
- ExtractTracks (source);
-}
-
-XMIDI::~XMIDI()
-{
- if (events)
- {
- for (int i=0; i < num_tracks; i++) {
- events[i]->DecerementCounter();
- events[i] = NULL;
- }
- //delete [] events;
- Free(events);
- }
-}
-
-XMIDIEventList *XMIDI::GetEventList (uint32_t track)
-{
- if (!events)
- {
- cerr << "No midi data in loaded." << endl;
- return 0;
- }
-
- if (track >= num_tracks)
- {
- cerr << "Can't retrieve MIDI data, track out of range" << endl;
- return 0;
- }
-
- return events[track];
-}
-
-// Sets current to the new event and updates list
-void XMIDI::CreateNewEvent (int time)
-{
- if (!list)
- {
- list = current = Calloc<midi_event>(); //new midi_event;
- if (time > 0)
- current->time = time;
- return;
- }
-
- if (time < 0 || list->time > time)
- {
- midi_event *event = Calloc<midi_event>(); //new midi_event;
- event->next = list;
- list = current = event;
- return;
- }
-
- if (!current || current->time > time)
- current = list;
-
- while (current->next)
- {
- if (current->next->time > time)
- {
- midi_event *event = Calloc<midi_event>(); //new midi_event;
-
- event->next = current->next;
- current->next = event;
- current = event;
- current->time = time;
- return;
- }
-
- current = current->next;
- }
-
- current->next = Calloc<midi_event>(); //new midi_event;
- current = current->next;
- current->time = time;
-}
-
-//
-// GetVLQ
-//
-// Get a Conventional Variable Length Quantity
-//
-int XMIDI::GetVLQ (DataSource *source, uint32_t &quant)
-{
- int i;
- quant = 0;
- unsigned int data;
-
- for (i = 0; i < 4; i++)
- {
- data = source->read1();
- quant <<= 7;
- quant |= data & 0x7F;
-
- if (!(data & 0x80))
- {
- i++;
- break;
- }
-
- }
- return i;
-}
-
-//
-// GetVLQ2
-//
-// Get a XMIDI Variable Length Quantity
-//
-int XMIDI::GetVLQ2 (DataSource *source, uint32_t &quant)
-{
- int i;
- quant = 0;
- int data = 0;
-
- for (i = 0; i < 4; i++)
- {
- data = source->read1();
- if (data & 0x80)
- {
- source->skip(-1);
- break;
- }
- quant += data;
- }
- return i;
-}
-
-//
-// MovePatchVolAndPan.
-//
-// Well, this is just a modified version of what that method used to do. This
-// is a massive optimization. Speed up should be quite impressive
-//
-void XMIDI::ApplyFirstState(first_state &fs, int chan_mask)
-{
- for (int channel = 0; channel < 16; channel++)
- {
- midi_event *patch = fs.patch[channel];
- midi_event *vol = fs.vol[channel];
- midi_event *pan = fs.pan[channel];
- midi_event *bank = fs.bank[channel];
- midi_event *reverb = NULL;
- midi_event *chorus = NULL;
- midi_event *temp;
-
- // Got no patch change, return and don't try fixing it
- if (!patch || !(chan_mask & 1 << channel)) continue;
-#if 0
- std::cout << "Channel: " << channel+1 << std::endl;
- std::cout << "Patch: " << (unsigned int) patch->data[0] << " @ " << patch->time << std::endl;
- if (bank) std::cout << " Bank: " << (unsigned int) bank->data[1] << " @ " << bank->time << std::endl;
- if (vol) std::cout << " Vol: " << (unsigned int) vol->data[1] << " @ " << vol->time << std::endl;
- if (pan) std::cout << " Pan: " << ((signed int) pan->data[1])-64 << " @ " << pan->time << std::endl;
- std::cout << std::endl;
-#endif
-
- // Copy Patch Change Event
- temp = patch;
- patch = Calloc<midi_event>(); //new midi_event;
- patch->time = temp->time;
- patch->status = channel|(MIDI_STATUS_PROG_CHANGE << 4);
- patch->data[0] = temp->data[0];
-
- // Copy Volume
- if (vol && (vol->time > patch->time+PATCH_VOL_PAN_BIAS || vol->time < patch->time-PATCH_VOL_PAN_BIAS))
- vol = NULL;
-
- temp = vol;
- vol = Calloc<midi_event>(); //new midi_event;
- vol->status = channel|(MIDI_STATUS_CONTROLLER << 4);
- vol->data[0] = 7;
-
- if (!temp)
- {
- vol->data[1] = 90;
- }
- else
- vol->data[1] = temp->data[1];
-
-
- // Copy Bank
- if (bank && (bank->time > patch->time+PATCH_VOL_PAN_BIAS || bank->time < patch->time-PATCH_VOL_PAN_BIAS))
- bank = NULL;
-
- temp = bank;
-
- bank = Calloc<midi_event>(); //new midi_event;
- bank->status = channel|(MIDI_STATUS_CONTROLLER << 4);
-
- if (!temp)
- bank->data[1] = 0;
- else
- bank->data[1] = temp->data[1];
-
- // Copy Pan
- if (pan && (pan->time > patch->time+PATCH_VOL_PAN_BIAS || pan->time < patch->time-PATCH_VOL_PAN_BIAS))
- pan = NULL;
-
- temp = pan;
- pan = Calloc<midi_event>(); //new midi_event;
- pan->status = channel|(MIDI_STATUS_CONTROLLER << 4);
- pan->data[0] = 10;
-
- if (!temp)
- pan->data[1] = 64;
- else
- pan->data[1] = temp->data[1];
-
- if (do_reverb)
- {
- reverb = Calloc<midi_event>(); //new midi_event;
- reverb->status = channel|(MIDI_STATUS_CONTROLLER << 4);
- reverb->data[0] = 91;
- reverb->data[1] = reverb_value;
- }
-
- if (do_chorus)
- {
- chorus = Calloc<midi_event>(); //new midi_event;
- chorus->status = channel|(MIDI_STATUS_CONTROLLER << 4);
- chorus->data[0] = 93;
- chorus->data[1] = chorus_value;
- }
-
- vol->time = 0;
- pan->time = 0;
- patch->time = 0;
- bank->time = 0;
-
- if (do_reverb && do_chorus) reverb->next = chorus;
- else if (do_reverb) reverb->next = bank;
- if (do_chorus) chorus->next = bank;
- bank->next = vol;
- vol->next = pan;
- pan->next = patch;
-
- patch->next = list;
- if (do_reverb) list = reverb;
- else if (do_chorus) list = chorus;
- else list = bank;
- }
-}
-
-
-//
-// AdjustTimings
-//
-// It converts the midi's to use 120 Hz timing, and also calcs the duration of
-// the notes. It also strips the tempo events, and adds it's own
-//
-// This is used by Midi's ONLY! It will do nothing with Xmidi
-//
-void XMIDI::AdjustTimings(uint32_t ppqn)
-{
- uint32_t tempo = 500000;
- uint32_t time_prev = 0;
- uint32_t hs_rem = 0;
- uint32_t hs = 0;
-
- ppqn *= 10000;
-
- // Virtual playing
- NoteStack notes;
-
- for (midi_event *event = list; event; event = event->next) {
-
- // Note 64 bit int is required because multiplication by tempo can
- // require 52 bits in some circumstances
-
- uint64_t aim = event->time - time_prev;
- aim *= tempo;
-
- hs_rem += aim%ppqn;
- hs += aim/ppqn;
- hs += hs_rem/ppqn;
- hs_rem %= ppqn;
-
- time_prev = event->time;
- event->time = (hs*6)/5 + (6*hs_rem)/(5*ppqn);
-
- // Note on and note off handling
- if (event->status <= 0x9F) {
-
- // Add if it's a note on and remove if it's a note off
- if ((event->status>>4) == MIDI_STATUS_NOTE_ON && event->data[1])
- notes.Push(event);
- else {
- midi_event *prev = notes.FindAndPop(event);
- if (prev) prev->duration = event->time - prev->time;
- }
-
- }
- else if (event->status == 0xFF && event->data[0] == 0x51) {
-
- tempo = (event->buffer[0] << 16) +
- (event->buffer[1] << 8) +
- event->buffer[2];
-
- event->buffer[0] = 0x07;
- event->buffer[1] = 0xA1;
- event->buffer[2] = 0x20;
- }
- }
-
- //std::cout << "Max Polyphony: " << notes.GetMaxPolyphony() << std::endl;
- static const uint8_t tempo_buf[5] = { 0x51, 0x03, 0x07, 0xA1, 0x20 };
- BufferDataSource ds((uint8_t *)tempo_buf, 5);
- current = list;
- ConvertSystemMessage (0, 0xFF,&ds);
-}
-
-
-// Converts Events
-//
-// Source is at the first data byte
-// size 1 is single data byte (ConvertEvent Only)
-// size 2 is dual data byte
-// size 3 is XMI Note on (ConvertNote only)
-// Returns bytes converted
-//
-// ConvertNote is used for Note On's and Note offs
-// ConvertSystemMessage is used for SysEx events and Meta events
-// ConvertEvent is used for everything else
-
-int XMIDI::ConvertEvent (const int time, uint8_t status, DataSource *source, const int size, first_state &fs)
-{
- int data;
-
- data = source->read1();
-
- // Little hacks for EMIDI
-
- if (use_emidi_112 && (status >> 4) == MIDI_STATUS_PROG_CHANGE)
- {
- // Discard all normal program changes if we are using emidi 112
- return 1;
- }
- else if (is_emidi && (status >> 4) == MIDI_STATUS_CONTROLLER && data == EMIDI_CONTROLLER_PROGRAM_CHANGE)
- {
- // Convert it into a normal program change event
- use_emidi_112 = true;
- status = (status&0x0F) | (MIDI_STATUS_PROG_CHANGE<<4);
- data = source->read1();
- source->skip(-1);
- }
-
- if (use_emidi_113 && (status >> 4) == MIDI_STATUS_CONTROLLER && data == 7)
- {
- // Discard all normal volume changes if we are using emidi 113
- source->skip(1);
- return 2;
- }
- else if (is_emidi && (status >> 4) == MIDI_STATUS_CONTROLLER && data == EMIDI_CONTROLLER_VOLUME)
- {
- // Convert it into a normal program change event
- use_emidi_113 = true;
- data = 7;
- }
-
-
- // Bank changes are handled here
- if ((status >> 4) == 0xB && data == 0)
- {
- data = source->read1();
-
- bank127[status&0xF] = false;
-
- if (convert_type == XMIDI_CONVERT_MT32_TO_GM || convert_type == XMIDI_CONVERT_MT32_TO_GS
- || convert_type == XMIDI_CONVERT_MT32_TO_GS127)
- return 2;
-
- CreateNewEvent (time);
- current->status = status;
- current->data[0] = 0;
- current->data[1] = data;
-
- // Set the bank
- if (!fs.bank[status&0xF] || fs.bank[status&0xF]->time > time) fs.bank[status&0xF] = current;
-
- if (convert_type == XMIDI_CONVERT_GS127_TO_GS && data == 127)
- bank127[status&0xF] = true;
-
- return 2;
- }
-
- // Handling for patch change mt32 conversion, probably should go elsewhere
- if ((status >> 4) == 0xC && (status&0xF) != 9 && convert_type != XMIDI_CONVERT_NOCONVERSION)
- {
- if (convert_type == XMIDI_CONVERT_MT32_TO_GM)
- {
- data = mt32asgm[data];
- }
- else if ((convert_type == XMIDI_CONVERT_GS127_TO_GS && bank127[status&0xF]) ||
- convert_type == XMIDI_CONVERT_MT32_TO_GS)
- {
- CreateNewEvent (time);
- current->status = 0xB0 | (status&0xF);
- current->data[0] = 0;
- current->data[1] = mt32asgs[data*2+1];
-
- data = mt32asgs[data*2];
-
- // Set the bank
- if (!fs.bank[status&0xF] || fs.bank[status&0xF]->time > time) fs.bank[status&0xF] = current;
- }
- else if (convert_type == XMIDI_CONVERT_MT32_TO_GS127)
- {
- CreateNewEvent (time);
- current->status = 0xB0 | (status&0xF);
- current->data[0] = 0;
- current->data[1] = 127;
-
- // Set the bank
- if (!fs.bank[status&0xF] || fs.bank[status&0xF]->time > time) fs.bank[status&0xF] = current;
- }
- }// Disable patch changes on Track 10 is doing a conversion
- else if ((status >> 4) == 0xC && (status&0xF) == 9 && convert_type != XMIDI_CONVERT_NOCONVERSION)
- {
- return size;
- }
-
- CreateNewEvent (time);
- current->status = status;
-
- current->data[0] = data;
-
- // Check for patch change, and update fs if req
- if ((status >> 4) == 0xC) {
- if (!fs.patch[status&0xF] || fs.patch[status&0xF]->time > time)
- fs.patch[status&0xF] = current;
- }
- // Controllers
- else if ((status >> 4) == 0xB) {
- // Volume
- if (current->data[0] == 7) {
- if (!fs.vol[status&0xF] || fs.vol[status&0xF]->time > time)
- fs.vol[status&0xF] = current;
- }
- // Pan
- else if (current->data[0] == 10) {
- if (!fs.pan[status&0xF] || fs.pan[status&0xF]->time > time)
- fs.pan[status&0xF] = current;
- }
- }
-
- if (size == 1)
- return 1;
-
- current->data[1] = source->read1();
-
- return 2;
-}
-
-int XMIDI::ConvertNote (const int time, const uint8_t status, DataSource *source, const int size)
-{
- uint32_t delta = 0;
- int data;
-
- data = source->read1();
-
- CreateNewEvent (time);
- current->status = status;
-
- current->data[0] = data;
- current->data[1] = source->read1();
-
- if (size == 2)
- return 2;
-
- // XMI Note On handling
-
- // Get the duration
- int i = GetVLQ (source, delta);
-
- // Set the duration
- current->duration = delta;
-
- // This is an optimization
- midi_event *prev = current;
-
- // Create a note off
- CreateNewEvent (time+delta);
-
- current->status = status;
- current->data[0] = data;
- current->data[1] = 0;
-
- // Optimization
- current = prev;
-
- return i + 2;
-}
-
-// Simple routine to convert system messages
-int XMIDI::ConvertSystemMessage (const int time, const uint8_t status, DataSource *source)
-{
- int i=0;
-
- CreateNewEvent (time);
- current->status = status;
-
- // Handling of Meta events
- if (status == 0xFF)
- {
- current->data[0] = source->read1();
- i++;
- }
-
- i += GetVLQ (source, current->len);
-
- if (!current->len)
- {
- current->buffer = NULL;
- return i;
- }
-
- current->buffer = Malloc<uint8_t >(current->len);
-
- source->read (reinterpret_cast<uint8_t *>(current->buffer), current->len);
-
- return i+current->len;
-}
-
-// XMIDI and Midi to List. Returns bit mask of channels used
-int XMIDI::ConvertFiletoList (DataSource *source, const bool is_xmi, first_state &fs)
-{
- int time = 0; // 120th of a second
- uint32_t data;
- int end = 0;
- uint32_t status = 0;
- int play_size = 2;
- int file_size = source->getSize();
- int retval = 0;
-
- if (is_xmi) play_size = 3;
-
- use_emidi_112 = false;
- use_emidi_113 = false;
-
- while (!end && source->getPos() < file_size)
- {
- if (!is_xmi)
- {
- GetVLQ (source, data);
- time += data;
-
- data = source->read1();
-
- if (data >= 0x80)
- {
- status = data;
- }
- else
- source->skip (-1);
- }
- else
- {
- GetVLQ2 (source, data);
- time += data;
-
- status = source->read1();
- }
-
- switch (status >> 4)
- {
- case MIDI_STATUS_NOTE_ON:
- retval |= 1 << (status & 0xF);
- ConvertNote (time, status, source, play_size);
- break;
-
- case MIDI_STATUS_NOTE_OFF:
- ConvertNote (time, status, source, 2);
- break;
-
- // 2 byte data
-
- case MIDI_STATUS_CONTROLLER:
- if (is_emidi)
- {
- data = source->read1();
- if (data == EMIDI_CONTROLLER_TRACK_DESIGNATION)
- {
- data = source->read1();
-
- // Only convert 0 and 127 tracks
- if (data == 0 || data == 127) continue;
-
- // Discard all others
- return 0;
- }
- else if (data == EMIDI_CONTROLLER_TRACK_EXCLUSION)
- {
- data = source->read1();
-
- // It's not for some other track
- if (data != 0) continue;
-
- // Uh oh, this track is not for 0
- return 0;
- }
- source->skip (-1);
- }
- // We can convert like normal
-
- case MIDI_STATUS_AFTERTOUCH:
- case MIDI_STATUS_PITCH_WHEEL:
- if (is_emidi && (status >> 4))
- ConvertEvent (time, status, source, 2, fs);
- break;
-
-
- // 1 byte data
- case MIDI_STATUS_PROG_CHANGE:
- case MIDI_STATUS_PRESSURE:
- ConvertEvent (time, status, source, 1, fs);
- break;
-
-
- case MIDI_STATUS_SYSEX:
- if (status == 0xFF)
- {
- int pos = source->getPos();
- uint32_t data = source->read1();
-
- if (data == 0x2F) // End, of track
- end = 1;
- else if (data == 0x51 && is_xmi) // XMIDI doesn't use tempo
- {
- GetVLQ (source, data);
- source->skip(data);
- break;
- }
-
- source->seek (pos);
- }
- ConvertSystemMessage (time, status, source);
- break;
-
- default:
- break;
- }
-
- }
-
- return retval;
-}
-
-// Assumes correct xmidi
-int XMIDI::ExtractTracksFromXmi (DataSource *source)
-{
- int num = 0;
- uint32_t len = 0;
- uint8_t buf[32];
-
- first_state fs;
-
- while (source->getPos() < source->getSize() && num != num_tracks)
- {
- // Read first 4 bytes of name
- source->read (buf, 4);
- len = source->read4high();
-
- // Skip the FORM entries
- if (!memcmp(buf,"FORM",4))
- {
- source->skip (4);
- source->read (buf, 4);
- len = source->read4high();
- }
-
- if (memcmp(buf,"EVNT",4))
- {
- source->skip ((len+1)&~1);
- continue;
- }
-
- list = NULL;
- memset(&fs, 0, sizeof(fs));
-
- int begin = source->getPos ();
-
- // Convert it
- int chan_mask = ConvertFiletoList (source, true, fs);
-
- // Apply the first state
- ApplyFirstState(fs, chan_mask);
-
- // Add tempo
- static const uint8_t tempo_buf[5] = { 0x51, 0x03, 0x07, 0xA1, 0x20 };
- BufferDataSource ds((uint8_t *)tempo_buf, 5);
- current = list;
- ConvertSystemMessage (0, 0xFF,&ds);
-
- // Set the list
- events[num]->events = list;
-
- // Increment Counter
- num++;
-
- // go to start of next track
- source->seek (begin + ((len+1)&~1));
- }
-
- // Return how many were converted
- return num;
-}
-
-int XMIDI::ExtractTracksFromMid (DataSource *source, const uint32_t ppqn, const int num_tracks, const bool type1)
-{
- int num = 0;
- uint32_t len = 0;
- uint8_t buf[32];
- int chan_mask = 0;
-
- first_state fs;
- memset(&fs, 0, sizeof(fs));
-
- list = NULL;
-
- while (source->getPos() < source->getSize() && num != num_tracks)
- {
- // Read first 4 bytes of name
- source->read (buf, 4);
- len = source->read4high();
-
- if (memcmp(buf,"MTrk",4))
- {
- source->skip (len);
- continue;
- }
-
- int begin = source->getPos ();
-
- // Convert it
- chan_mask |= ConvertFiletoList (source, false, fs);
-
- if (!type1) {
- ApplyFirstState(fs, chan_mask);
- AdjustTimings(ppqn);
- events[num]->events = list;
- list = NULL;
- memset(&fs, 0, sizeof(fs));
- chan_mask = 0;
- }
-
- // Increment Counter
- num++;
- source->seek (begin+len);
- }
-
- if (type1) {
- ApplyFirstState(fs, chan_mask);
- AdjustTimings(ppqn);
- events[0]->events = list;
- return num == num_tracks ? 1 : 0;
- }
-
- // Return how many were converted
- return num;
-}
-
-int XMIDI::ExtractTracks (DataSource *source)
-{
- uint32_t i = 0;
- int start;
- uint32_t len;
- uint32_t chunk_len;
- int count;
- uint8_t buf[32];
-
- string s;
-
- do_reverb = false;
- reverb_value = 0;
- do_chorus = true;
- chorus_value = 0;
-
-
- // Read first 4 bytes of header
- source->read (buf, 4);
-
- // Could be XMIDI
- if (!memcmp (buf, "FORM", 4))
- {
- // Read length of
- len = source->read4high();
-
- start = source->getPos();
-
- // Read 4 bytes of type
- source->read (buf, 4);
-
- // XDIRless XMIDI, we can handle them here.
- if (!memcmp (buf, "XMID", 4))
- {
- cerr << "Warning: XMIDI doesn't have XDIR" << endl;
- num_tracks = 1;
-
- } // Not an XMIDI that we recognise
- else if (memcmp (buf, "XDIR", 4))
- {
- cerr << "Not a recognised XMID" << endl;
- return 0;
-
- } // Seems Valid
- else
- {
- num_tracks = 0;
-
- for (i = 4; i < len; i++)
- {
- // Read 4 bytes of type
- source->read (buf, 4);
-
- // Read length of chunk
- chunk_len = source->read4high();
-
- // Add eight bytes
- i+=8;
-
- if (memcmp (buf, "INFO", 4))
- {
- // Must allign
- source->skip((chunk_len+1)&~1);
- i+= (chunk_len+1)&~1;
- continue;
- }
-
- // Must be at least 2 bytes long
- if (chunk_len < 2)
- break;
-
- num_tracks = source->read2();
- break;
- }
-
- // Didn't get to fill the header
- if (num_tracks == 0)
- {
- cerr << "Not a valid XMID" << endl;
- return 0;
- }
-
- // Ok now to start part 2
- // Goto the right place
- source->seek (start+((len+1)&~1));
-
- // Read 4 bytes of type
- source->read (buf, 4);
-
- // Not an XMID
- if (memcmp (buf, "CAT ", 4))
- {
- cerr << "Not a recognised XMID (" << buf[0] << buf[1] << buf[2] << buf[3] << ") should be (CAT )" << endl;
- return 0;
- }
-
- // Now read length of this track
- len = source->read4high();
-
- // Read 4 bytes of type
- source->read (buf, 4);
-
- // Not an XMID
- if (memcmp (buf, "XMID", 4))
- {
- cerr << "Not a recognised XMID (" << buf[0] << buf[1] << buf[2] << buf[3] << ") should be (XMID)" << endl;
- return 0;
- }
-
- }
-
- // Ok it's an XMID, so pass it to the ExtractCode
-
- events = Calloc<XMIDIEventList*>(num_tracks); //new midi_event *[info.tracks];
-
- for (i = 0; i < num_tracks; i++)
- events[i] = Calloc<XMIDIEventList>();
-
- count = ExtractTracksFromXmi (source);
-
- if (count != num_tracks)
- {
- cerr << "Error: unable to extract all (" << num_tracks << ") tracks specified from XMIDI. Only ("<< count << ")" << endl;
-
- int i = 0;
-
- for (i = 0; i < num_tracks; i++) {
- events[i]->DecerementCounter();
- events[i] = NULL;
- }
-
- //delete [] events;
- Free (events);
-
- return 0;
- }
-
- return 1;
-
- }// Definately a Midi
- else if (!memcmp (buf, "MThd", 4))
- {
- // Simple read length of header
- len = source->read4high();
-
- if (len < 6)
- {
- cerr << "Not a valid MIDI" << endl;
- return 0;
- }
-
- int type = source->read2high();
-
- int actual_num = num_tracks = source->read2high();
-
- // Type 1 only has 1 track, even though it says it has more
- if (type == 1) num_tracks = 1;
-
- events = Calloc<XMIDIEventList*>(num_tracks); //new midi_event *[info.tracks];
- const uint32_t ppqn = source->read2high();
-
- for (i = 0; i < num_tracks; i++)
- events[i] = Calloc<XMIDIEventList>();
-
- count = ExtractTracksFromMid (source, ppqn, actual_num, type == 1);
-
- if (count != num_tracks)
- {
- cerr << "Error: unable to extract all (" << num_tracks << ") tracks specified from MIDI. Only ("<< count << ")" << endl;
-
- for (i = 0; i < num_tracks; i++) {
- events[i]->DecerementCounter();
- events[i] = NULL;
- }
-
- Free (events);
-
- return 0;
-
- }
-
- return 1;
-
- }// A RIFF Midi, just pass the source back to this function at the start of the midi file
- else if (!memcmp (buf, "RIFF", 4))
- {
- // Read len
- len = source->read4();
-
- // Read 4 bytes of type
- source->read (buf, 4);
-
- // Not an RMID
- if (memcmp (buf, "RMID", 4))
- {
- cerr << "Invalid RMID" << endl;
- return 0;
- }
-
- // Is a RMID
-
- for (i = 4; i < len; i++)
- {
- // Read 4 bytes of type
- source->read (buf, 4);
-
- chunk_len = source->read4();
-
- i+=8;
-
- if (memcmp (buf, "data", 4))
- {
- // Must allign
- source->skip ((chunk_len+1)&~1);
- i+= (chunk_len+1)&~1;
- continue;
- }
-
- return ExtractTracks (source);
-
- }
-
- cerr << "Failed to find midi data in RIFF Midi" << endl;
- return 0;
- }
-
- return 0;
-}
-
-//
-// XMIDIEventList stuff
-//
-int XMIDIEventList::Write (const uint8_t *filename)
-{
-// FILE *file = fopen (filename, "wb"); // DARKE FIXME
-// FileDataSource ds(file);
-// int ret = Write(&ds);
-// fclose (file);
-// return ret;
- return 0;
-}
-
-int XMIDIEventList::Write (DataSource *dest)
-{
- int len = 0;
-
- if (!events)
- {
- cerr << "No midi data in loaded." << endl;
- return 0;
- }
-
- // This is so if using buffer datasource, the caller can know how big to make the buffer
- if (!dest)
- {
- // Header is 14 bytes int32_t and add the rest as well
- len = ConvertListToMTrk (NULL);
- return 14 + len;
- }
-
- dest->write1 ('M');
- dest->write1 ('T');
- dest->write1 ('h');
- dest->write1 ('d');
-
- dest->write4high (6);
-
- dest->write2high (0);
- dest->write2high (1);
- dest->write2high (60); // The PPQN
-
- len = ConvertListToMTrk (dest);
-
- return len + 14;
-}
-
-//
-// PutVLQ
-//
-// Write a Conventional Variable Length Quantity
-//
-int XMIDIEventList::PutVLQ(DataSource *dest, uint32_t value)
-{
- int buffer;
- int i = 1;
- buffer = value & 0x7F;
- while (value >>= 7)
- {
- buffer <<= 8;
- buffer |= ((value & 0x7F) | 0x80);
- i++;
- }
- if (!dest) return i;
- for (int j = 0; j < i; j++)
- {
- dest->write1(buffer & 0xFF);
- buffer >>= 8;
- }
-
- return i;
-}
-
-// Converts and event list to a MTrk
-// Returns bytes of the array
-// buf can be NULL
-uint32_t XMIDIEventList::ConvertListToMTrk (DataSource *dest)
-{
- int time = 0;
- int lasttime = 0;
- midi_event *event;
- uint32_t delta;
- uint8_t last_status = 0;
- uint32_t i = 8;
- uint32_t j;
- uint32_t size_pos=0;
-
- if (dest)
- {
- dest->write1('M');
- dest->write1('T');
- dest->write1('r');
- dest->write1('k');
-
- size_pos = dest->getPos();
- dest->skip(4);
- }
-
- for (event = events; event; event=event->next)
- {
- // We don't write the end of stream marker here, we'll do it later
- if (event->status == 0xFF && event->data[0] == 0x2f) {
- lasttime = event->time;
- continue;
- }
-
- delta = (event->time - time);
- time = event->time;
-
- i += PutVLQ (dest, delta);
-
- if ((event->status != last_status) || (event->status >= 0xF0))
- {
- if (dest) dest->write1(event->status);
- i++;
- }
-
- last_status = event->status;
-
- switch (event->status >> 4)
- {
- // 2 bytes data
- // Note off, Note on, Aftertouch, Controller and Pitch Wheel
- case 0x8: case 0x9: case 0xA: case 0xB: case 0xE:
- if (dest)
- {
- dest->write1(event->data[0]);
- dest->write1(event->data[1]);
- }
- i += 2;
- break;
-
-
- // 1 bytes data
- // Program Change and Channel Pressure
- case 0xC: case 0xD:
- if (dest) dest->write1(event->data[0]);
- i++;
- break;
-
-
- // Variable length
- // SysEx
- case 0xF:
- if (event->status == 0xFF)
- {
- if (dest) dest->write1(event->data[0]);
- i++;
- }
-
- i += PutVLQ (dest, event->len);
-
- if (event->len)
- {
- for (j = 0; j < event->len; j++)
- {
- if (dest) dest->write1(event->buffer[j]);
- i++;
- }
- }
-
- break;
-
-
- // Never occur
- default:
- cerr << "Not supposed to see this" << endl;
- break;
- }
- }
-
- // Write out end of stream marker
- if (lasttime > time) i += PutVLQ (dest, lasttime-time);
- else i += PutVLQ (dest, 0);
- if (dest) {
- dest->write1(0xFF);
- dest->write1(0x2F);
- }
- i += 2+PutVLQ (dest, 0);
-
- if (dest)
- {
- int cur_pos = dest->getPos();
- dest->seek (size_pos);
- dest->write4high (i-8);
- dest->seek (cur_pos);
- }
- return i;
-}
-
-
-void XMIDIEventList::DeleteEventList (midi_event *mlist)
-{
- midi_event *event;
- midi_event *next;
-
- next = mlist;
- event = mlist;
-
- while ((event = next))
- {
- next = event->next;
- // We only do this with sysex
- if ((event->status>>4) == 0xF && event->buffer) Free (event->buffer);
- Free (event);
- }
-}
-
-void XMIDIEventList::DecerementCounter()
-{
- if (--counter < 0) {
- DeleteEventList(events);
- Free(this);
- }
-}
--- a/Game/src/midi/xmidi.h
+++ /dev/null
@@ -1,306 +1,0 @@
-/*
-Copyright (C) 2000 Ryan Nunn
-
-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
-aint32_t with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-// Tab Size = 4
-
-#ifndef __XMIDI_h_
-#define __XMIDI_h_
-
-#include <string>
-//#include "common_types.h"
-#include "databuf.h"
-
-
-// Conversion types for Midi files
-#define XMIDI_CONVERT_NOCONVERSION 0
-#define XMIDI_CONVERT_MT32_TO_GM 1
-#define XMIDI_CONVERT_MT32_TO_GS 2
-#define XMIDI_CONVERT_MT32_TO_GS127 3
-#define XMIDI_CONVERT_OGG 4
-#define XMIDI_CONVERT_GS127_TO_GS 5
-#define XMIDI_CONVERT_EMIDI_GM 6 // For Duke3D! Selects General Midi tracks
-
-// Midi Status Bytes
-#define MIDI_STATUS_NOTE_OFF 0x8
-#define MIDI_STATUS_NOTE_ON 0x9
-#define MIDI_STATUS_AFTERTOUCH 0xA
-#define MIDI_STATUS_CONTROLLER 0xB
-#define MIDI_STATUS_PROG_CHANGE 0xC
-#define MIDI_STATUS_PRESSURE 0xD
-#define MIDI_STATUS_PITCH_WHEEL 0xE
-#define MIDI_STATUS_SYSEX 0xF
-
-// XMIDI Controllers
-#define XMIDI_CONTROLLER_CHAN_LOCK 0x6e // Channel Lock
-#define XMIDI_CONTROLLER_CHAN_LOCK_PROT 0x6f // Channel Lock Protect
-#define XMIDI_CONTROLLER_VOICE_PROT 0x70 // Voice Protect
-#define XMIDI_CONTROLLER_TIMBRE_PROT 0x71 // Timbre Protect
-#define XMIDI_CONTROLLER_BANK_CHANGE 0x72 // Bank Change
-#define XMIDI_CONTROLLER_IND_CTRL_PREFIX 0x73 // Indirect Controller Prefix
-#define XMIDI_CONTROLLER_FOR_LOOP 0x74 // For Loop
-#define XMIDI_CONTROLLER_NEXT_BREAK 0x75 // Next/Break
-#define XMIDI_CONTROLLER_CLEAR_BB_COUNT 0x76 // Clear Beat/Bar Count
-#define XMIDI_CONTROLLER_CALLBACK_TRIG 0x77 // Callback Trigger
-#define XMIDI_CONTROLLER_SEQ_BRANCH_INDEX 0x78 // Sequence Branch Index
-
-#define EMIDI_CONTROLLER_TRACK_DESIGNATION 110 // Track Designation
-#define EMIDI_CONTROLLER_TRACK_EXCLUSION 111 // Track Exclusion
-#define EMIDI_CONTROLLER_PROGRAM_CHANGE 112 // Program Change
-#define EMIDI_CONTROLLER_VOLUME 113 // Volume
-#define EMIDI_CONTROLLER_LOOP_BEGIN XMIDI_CONTROLLER_FOR_LOOP
-#define EMIDI_CONTROLLER_LOOP_END XMIDI_CONTROLLER_NEXT_BREAK
-
-
-// Maximum number of for loops we'll allow (used by win_midiout)
-#define XMIDI_MAX_FOR_LOOP_COUNT 128
-
-template <class T> class GammaTable;
-
-struct midi_event
-{
- int time;
- uint8_t status;
-
- uint8_t data[2];
-
- uint32_t len; // Length of SysEx Data
- uint8_t *buffer; // SysEx Data
- int duration; // Duration of note (120 Hz)
- midi_event *next_note; // The next note on the stack
- uint32_t note_time; // Time note stops playing (6000th of second)
- midi_event *next;
-};
-
-class NoteStack {
- midi_event *notes; // Top of the stack
- int polyphony;
- int max_polyphony;
-public:
-
- NoteStack() : notes(0), polyphony(0), max_polyphony(0) { }
-
- // Just clear it. Don't care about what's actually in it
- void clear() {
- notes=0;
- polyphony=0;
- max_polyphony=0;
- }
-
- // Pops the top of the stack if its off_time is <= time (6000th of second)
- inline midi_event *PopTime(uint32_t time) {
- if (notes && notes->note_time <= time) {
- midi_event *note = notes;
- notes = note->next_note;
- note->next_note = 0;
- polyphony--;
- return note;
- }
-
- return 0;
- }
-
- // Pops the top of the stack
- inline midi_event *Pop() {
- if (notes) {
- midi_event *note = notes;
- notes = note->next_note;
- note->next_note = 0;
- polyphony--;
- return note;
- }
-
- return 0;
- }
-
- // Pops the top of the stack
- inline midi_event *Remove(midi_event *event) {
- midi_event *prev = 0;
- midi_event *note = notes;
- while (note) {
-
- if (note == event) {
- if (prev) prev->next_note = note->next_note;
- else notes = note->next_note;
- note->next_note = 0;
- polyphony--;
- return note;
- }
- prev = note;
- note = note->next_note;
- }
- return 0;
- }
-
- // Finds the note that has same pitch and channel, and pops it
- inline midi_event *FindAndPop(midi_event *event) {
-
- midi_event *prev = 0;
- midi_event *note = notes;
- while (note) {
-
- if ((note->status & 0xF) == (event->status & 0xF) && note->data[0] == event->data[0]) {
- if (prev) prev->next_note = note->next_note;
- else notes = note->next_note;
- note->next_note = 0;
- polyphony--;
- return note;
- }
- prev = note;
- note = note->next_note;
- }
- return 0;
- }
-
- // Pushes a note onto the top of the stack
- inline void Push(midi_event *event) {
- event->next_note = notes;
- notes = event;
- polyphony++;
- if (max_polyphony < polyphony) max_polyphony = polyphony;
- }
-
-
- inline void Push(midi_event *event, uint32_t time) {
- event->note_time = time;
- event->next_note = 0;
-
- polyphony++;
- if (max_polyphony < polyphony) max_polyphony = polyphony;
-
- if (!notes || time <= notes->note_time) {
- event->next_note = notes;
- notes = event;
- }
- else {
- midi_event *prev = notes;
- while (prev) {
- midi_event *note = prev->next_note;
-
- if (!note || time <= note->note_time) {
- event->next_note = note;
- prev->next_note = event;
- return;
- }
- prev = note;
- }
- }
- }
-
- inline int GetPolyphony() {
- return polyphony;
- }
-
- inline int GetMaxPolyphony() {
- return max_polyphony;
- }
-};
-
-class XMIDIEventList
-{
- int counter;
-
- // Helper funcs for Write
- int PutVLQ(DataSource *dest, uint32_t value);
- uint32_t ConvertListToMTrk (DataSource *dest);
-
- static void DeleteEventList (midi_event *list);
-
-public:
- midi_event *events;
-
- // Write this list to a file/buffer
- int Write (const uint8_t *filename);
- int Write (DataSource *dest);
-
- // Increments the counter
- void IncerementCounter () { counter++; }
-
- // Decrement the counter and delete the event list, if possible
- void DecerementCounter ();
-};
-
-class XMIDI
-{
-protected:
- uint16_t num_tracks;
-
-private:
- XMIDIEventList **events;
-
- midi_event *list;
- midi_event *current;
- midi_event *notes_on;
-
- const static uint8_t mt32asgm[128];
- const static uint8_t mt32asgs[256];
- bool bank127[16];
- int convert_type;
-
- bool is_emidi;
- bool use_emidi_112;
- bool use_emidi_113;
-
- bool do_reverb;
- bool do_chorus;
- int chorus_value;
- int reverb_value;
-
-public:
- XMIDI(DataSource *source, int pconvert);
- ~XMIDI();
-
- int number_of_tracks() { return num_tracks; }
-
- // External Event list functions
- XMIDIEventList *GetEventList (uint32_t track);
-
- // Not yet implimented
- // int apply_patch (int track, DataSource *source);
-
-private:
- XMIDI(); // No default constructor
-
- struct first_state { // Status, Data[0]
- midi_event *patch[16]; // 0xC
- midi_event *bank[16]; // 0xB, 0
- midi_event *pan[16]; // 0xB, 7
- midi_event *vol[16]; // 0xB, 10
- };
-
- // List manipulation
- void CreateNewEvent (int time);
-
- // Variable length quantity
- int GetVLQ (DataSource *source, uint32_t &quant);
- int GetVLQ2 (DataSource *source, uint32_t &quant);
-
- void AdjustTimings(uint32_t ppqn); // This is used by Midi's ONLY!
- void ApplyFirstState(first_state &fs, int chan_mask);
-
- int ConvertNote (const int time, const uint8_t status, DataSource *source, const int size);
- int ConvertEvent (const int time, uint8_t status, DataSource *source, const int size, first_state& fs);
- int ConvertSystemMessage (const int time, const uint8_t status, DataSource *source);
-
- int ConvertFiletoList (DataSource *source, const bool is_xmi, first_state& fs);
-
- int ExtractTracksFromXmi (DataSource *source);
- int ExtractTracksFromMid (DataSource *source, const uint32_t ppqn, const int num_tracks, const bool type1);
-
- int ExtractTracks (DataSource *source);
-};
-#endif