diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/adlmidi.cpp | 91 | ||||
-rw-r--r-- | src/adlmidi_load.cpp | 42 | ||||
-rw-r--r-- | src/adlmidi_midiplay.cpp | 204 | ||||
-rw-r--r-- | src/adlmidi_mus2mid.h | 9 | ||||
-rw-r--r-- | src/adlmidi_opl3.cpp | 32 | ||||
-rw-r--r-- | src/adlmidi_private.cpp | 4 | ||||
-rw-r--r-- | src/adlmidi_private.hpp | 92 | ||||
-rw-r--r-- | src/adlmidi_xmi2mid.h | 9 | ||||
-rw-r--r-- | src/fraction.hpp (renamed from src/fraction.h) | 0 |
9 files changed, 406 insertions, 77 deletions
diff --git a/src/adlmidi.cpp b/src/adlmidi.cpp index 59d7a7e..dc9c980 100644 --- a/src/adlmidi.cpp +++ b/src/adlmidi.cpp @@ -23,7 +23,11 @@ #include "adlmidi_private.hpp" +#ifdef ADLMIDI_HW_OPL +static const unsigned MaxCards = 1; +#else static const unsigned MaxCards = 100; +#endif /*---------------------------EXPORTS---------------------------*/ @@ -31,7 +35,20 @@ ADLMIDI_EXPORT struct ADL_MIDIPlayer *adl_init(long sample_rate) { ADL_MIDIPlayer *midi_device; midi_device = (ADL_MIDIPlayer *)malloc(sizeof(ADL_MIDIPlayer)); + if(!midi_device) + { + ADLMIDI_ErrorString = "Can't initialize ADLMIDI: out of memory!"; + return NULL; + } + MIDIplay *player = new MIDIplay; + if(!player) + { + free(midi_device); + ADLMIDI_ErrorString = "Can't initialize ADLMIDI: out of memory!"; + return NULL; + } + midi_device->adl_midiPlayer = player; player->m_setup.PCM_RATE = static_cast<unsigned long>(sample_rate); player->m_setup.mindelay = 1.0 / (double)player->m_setup.PCM_RATE; @@ -52,7 +69,7 @@ ADLMIDI_EXPORT int adl_setNumCards(ADL_MIDIPlayer *device, int numCards) { std::stringstream s; s << "number of cards may only be 1.." << MaxCards << ".\n"; - ADLMIDI_ErrorString = s.str(); + play->setErrorString(s.str()); return -1; } @@ -83,7 +100,7 @@ ADLMIDI_EXPORT int adl_setBank(ADL_MIDIPlayer *device, int bank) { std::stringstream s; s << "bank number may only be 0.." << (NumBanks - 1) << ".\n"; - ADLMIDI_ErrorString = s.str(); + play->setErrorString(s.str()); return -1; } @@ -113,7 +130,7 @@ ADLMIDI_EXPORT int adl_setNumFourOpsChn(ADL_MIDIPlayer *device, int ops4) { std::stringstream s; s << "number of four-op channels may only be 0.." << (6 * (play->m_setup.NumCards)) << " when " << play->m_setup.NumCards << " OPL3 cards are used.\n"; - ADLMIDI_ErrorString = s.str(); + play->setErrorString(s.str()); return -1; } @@ -178,8 +195,6 @@ ADLMIDI_EXPORT void adl_setVolumeRangeModel(struct ADL_MIDIPlayer *device, int v ADLMIDI_EXPORT int adl_openBankFile(struct ADL_MIDIPlayer *device, char *filePath) { - ADLMIDI_ErrorString.clear(); - if(device && device->adl_midiPlayer) { MIDIplay *play = reinterpret_cast<MIDIplay *>(device->adl_midiPlayer); @@ -187,8 +202,9 @@ ADLMIDI_EXPORT int adl_openBankFile(struct ADL_MIDIPlayer *device, char *filePat play->m_setup.backup_samples_size = 0; if(!play->LoadBank(filePath)) { - if(ADLMIDI_ErrorString.empty()) - ADLMIDI_ErrorString = "ADL MIDI: Can't load file"; + std::string err = play->getErrorString(); + if(err.empty()) + play->setErrorString("ADL MIDI: Can't load file"); return -1; } else return 0; @@ -200,8 +216,6 @@ ADLMIDI_EXPORT int adl_openBankFile(struct ADL_MIDIPlayer *device, char *filePat ADLMIDI_EXPORT int adl_openBankData(struct ADL_MIDIPlayer *device, void *mem, long size) { - ADLMIDI_ErrorString.clear(); - if(device && device->adl_midiPlayer) { MIDIplay *play = reinterpret_cast<MIDIplay *>(device->adl_midiPlayer); @@ -209,8 +223,9 @@ ADLMIDI_EXPORT int adl_openBankData(struct ADL_MIDIPlayer *device, void *mem, lo play->m_setup.backup_samples_size = 0; if(!play->LoadBank(mem, static_cast<size_t>(size))) { - if(ADLMIDI_ErrorString.empty()) - ADLMIDI_ErrorString = "ADL MIDI: Can't load data from memory"; + std::string err = play->getErrorString(); + if(err.empty()) + play->setErrorString("ADL MIDI: Can't load data from memory"); return -1; } else return 0; @@ -222,8 +237,6 @@ ADLMIDI_EXPORT int adl_openBankData(struct ADL_MIDIPlayer *device, void *mem, lo ADLMIDI_EXPORT int adl_openFile(ADL_MIDIPlayer *device, char *filePath) { - ADLMIDI_ErrorString.clear(); - if(device && device->adl_midiPlayer) { MIDIplay *play = reinterpret_cast<MIDIplay *>(device->adl_midiPlayer); @@ -231,8 +244,9 @@ ADLMIDI_EXPORT int adl_openFile(ADL_MIDIPlayer *device, char *filePath) play->m_setup.backup_samples_size = 0; if(!play->LoadMIDI(filePath)) { - if(ADLMIDI_ErrorString.empty()) - ADLMIDI_ErrorString = "ADL MIDI: Can't load file"; + std::string err = play->getErrorString(); + if(err.empty()) + play->setErrorString("ADL MIDI: Can't load file"); return -1; } else return 0; @@ -244,8 +258,6 @@ ADLMIDI_EXPORT int adl_openFile(ADL_MIDIPlayer *device, char *filePath) ADLMIDI_EXPORT int adl_openData(ADL_MIDIPlayer *device, void *mem, long size) { - ADLMIDI_ErrorString.clear(); - if(device && device->adl_midiPlayer) { MIDIplay *play = reinterpret_cast<MIDIplay *>(device->adl_midiPlayer); @@ -253,13 +265,13 @@ ADLMIDI_EXPORT int adl_openData(ADL_MIDIPlayer *device, void *mem, long size) play->m_setup.backup_samples_size = 0; if(!play->LoadMIDI(mem, static_cast<size_t>(size))) { - if(ADLMIDI_ErrorString.empty()) - ADLMIDI_ErrorString = "ADL MIDI: Can't load data from memory"; + std::string err = play->getErrorString(); + if(err.empty()) + play->setErrorString("ADL MIDI: Can't load data from memory"); return -1; } else return 0; } - ADLMIDI_ErrorString = "Can't load file: ADL MIDI is not initialized"; return -1; } @@ -274,16 +286,35 @@ ADLMIDI_EXPORT const char *adl_emulatorName() #endif } +ADLMIDI_EXPORT const char *adl_linkedLibraryVersion() +{ + return ADLMIDI_VERSION; +} + + ADLMIDI_EXPORT const char *adl_errorString() { return ADLMIDI_ErrorString.c_str(); } +ADLMIDI_EXPORT const char *adl_errorInfo(ADL_MIDIPlayer *device) +{ + if(!device) + return adl_errorString(); + MIDIplay *play = reinterpret_cast<MIDIplay *>(device->adl_midiPlayer); + if(!play) + return adl_errorString(); + return play->getErrorString().c_str(); +} + ADLMIDI_EXPORT const char *adl_getMusicTitle(ADL_MIDIPlayer *device) { if(!device) return ""; - return reinterpret_cast<MIDIplay *>(device->adl_midiPlayer)->musTitle.c_str(); + MIDIplay *play = reinterpret_cast<MIDIplay *>(device->adl_midiPlayer); + if(!play) + return ""; + return play->musTitle.c_str(); } ADLMIDI_EXPORT void adl_close(ADL_MIDIPlayer *device) @@ -477,6 +508,9 @@ inline static void SendStereoAudio(MIDIplay::Setup &device, ADLMIDI_EXPORT int adl_play(ADL_MIDIPlayer *device, int sampleCount, short *out) { + #ifdef ADLMIDI_HW_OPL + return 0; + #else sampleCount -= sampleCount % 2; //Avoid even sample requests if(sampleCount < 0) return 0; @@ -573,11 +607,15 @@ ADLMIDI_EXPORT int adl_play(ADL_MIDIPlayer *device, int sampleCount, short *out) } return static_cast<int>(gotten_len); + #endif } ADLMIDI_EXPORT int adl_generate(ADL_MIDIPlayer *device, int sampleCount, short *out) { + #ifdef ADLMIDI_HW_OPL + return 0; + #else sampleCount -= sampleCount % 2; //Avoid even sample requests if(sampleCount < 0) return 0; @@ -617,4 +655,15 @@ ADLMIDI_EXPORT int adl_generate(ADL_MIDIPlayer *device, int sampleCount, short * } return sampleCount; + #endif +} + +ADLMIDI_EXPORT double adl_tickEvents(ADL_MIDIPlayer *device, double seconds, double granuality) +{ + if(!device) + return -1.0; + MIDIplay *player = reinterpret_cast<MIDIplay *>(device->adl_midiPlayer); + if(!player) + return -1.0; + return player->Tick(seconds, granuality); } diff --git a/src/adlmidi_load.cpp b/src/adlmidi_load.cpp index 16881d4..76765dc 100644 --- a/src/adlmidi_load.cpp +++ b/src/adlmidi_load.cpp @@ -176,7 +176,7 @@ bool MIDIplay::LoadBank(MIDIplay::fileReader &fr) ADL_UNUSED(fsize); if(!fr.isValid()) { - ADLMIDI_ErrorString = "Custom bank: Invalid data stream!"; + errorStringOut = "Custom bank: Invalid data stream!"; return false; } @@ -190,27 +190,27 @@ bool MIDIplay::LoadBank(MIDIplay::fileReader &fr) if(fr.read(magic, 1, 11) != 11) { - ADLMIDI_ErrorString = "Custom bank: Can't read magic number!"; + errorStringOut = "Custom bank: Can't read magic number!"; return false; } if(strncmp(magic, wopl3_magic, 11) != 0) { - ADLMIDI_ErrorString = "Custom bank: Invalid magic number!"; + errorStringOut = "Custom bank: Invalid magic number!"; return false; } uint8_t version_raw[2]; if(fr.read(version_raw, 1, 2) != 2) { - ADLMIDI_ErrorString = "Custom bank: Can't read version!"; + errorStringOut = "Custom bank: Can't read version!"; return false; } version = toUint16LE(version_raw); if(version > wopl_latest_version) { - ADLMIDI_ErrorString = "Custom bank: Unsupported WOPL version!"; + errorStringOut = "Custom bank: Unsupported WOPL version!"; return false; } @@ -218,7 +218,7 @@ bool MIDIplay::LoadBank(MIDIplay::fileReader &fr) memset(head, 0, 6); if(fr.read(head, 1, 6) != 6) { - ADLMIDI_ErrorString = "Custom bank: Can't read header!"; + errorStringOut = "Custom bank: Can't read header!"; return false; } @@ -227,7 +227,7 @@ bool MIDIplay::LoadBank(MIDIplay::fileReader &fr) if((count_melodic_banks < 1) || (count_percusive_banks < 1)) { - ADLMIDI_ErrorString = "Custom bank: Too few banks in this file!"; + errorStringOut = "Custom bank: Too few banks in this file!"; return false; } @@ -248,7 +248,7 @@ bool MIDIplay::LoadBank(MIDIplay::fileReader &fr) uint8_t bank_meta[34]; if(fr.read(bank_meta, 1, 34) != 34) { - ADLMIDI_ErrorString = "Custom bank: Fail to read melodic bank meta-data!"; + errorStringOut = "Custom bank: Fail to read melodic bank meta-data!"; return false; } //strncpy(bankMeta.name, char_p(bank_meta), 32); @@ -261,7 +261,7 @@ bool MIDIplay::LoadBank(MIDIplay::fileReader &fr) uint8_t bank_meta[34]; if(fr.read(bank_meta, 1, 34) != 34) { - ADLMIDI_ErrorString = "Custom bank: Fail to read melodic bank meta-data!"; + errorStringOut = "Custom bank: Fail to read melodic bank meta-data!"; return false; } //strncpy(bankMeta.name, char_p(bank_meta), 32); @@ -286,7 +286,7 @@ tryAgain: { opl.dynamic_metainstruments.clear(); opl.dynamic_instruments.clear(); - ADLMIDI_ErrorString = "Custom bank: Fail to read instrument!"; + errorStringOut = "Custom bank: Fail to read instrument!"; return false; } @@ -356,9 +356,9 @@ bool MIDIplay::LoadMIDI(MIDIplay::fileReader &fr) if(!fr.isValid()) { - ADLMIDI_ErrorString = "Invalid data stream!\n"; + errorStringOut = "Invalid data stream!\n"; #ifndef _WIN32 - ADLMIDI_ErrorString += std::strerror(errno); + errorStringOut += std::strerror(errno); #endif return false; } @@ -423,7 +423,7 @@ riffskip: uint8_t *mus = (uint8_t *)malloc(mus_len); if(!mus) { - ADLMIDI_ErrorString = "Out of memory!"; + errorStringOut = "Out of memory!"; return false; } fr.read(mus, 1, mus_len); @@ -437,7 +437,7 @@ riffskip: if(mus) free(mus); if(m2mret < 0) { - ADLMIDI_ErrorString = "Invalid MUS/DMX data format!"; + errorStringOut = "Invalid MUS/DMX data format!"; return false; } cvt_buf.reset(mid); @@ -451,7 +451,7 @@ riffskip: if(std::memcmp(HeaderBuf + 8, "XDIR", 4) != 0) { fr.close(); - ADLMIDI_ErrorString = fr._fileName + ": Invalid format\n"; + errorStringOut = fr._fileName + ": Invalid format\n"; return false; } @@ -461,7 +461,7 @@ riffskip: uint8_t *mus = (uint8_t *)malloc(mus_len); if(!mus) { - ADLMIDI_ErrorString = "Out of memory!"; + errorStringOut = "Out of memory!"; return false; } fr.read(mus, 1, mus_len); @@ -475,7 +475,7 @@ riffskip: if(mus) free(mus); if(m2mret < 0) { - ADLMIDI_ErrorString = "Invalid XMI data format!"; + errorStringOut = "Invalid XMI data format!"; return false; } cvt_buf.reset(mid); @@ -613,7 +613,7 @@ riffskip: if(std::memcmp(HeaderBuf, "MThd\0\0\0\6", 8) != 0) { fr.close(); - ADLMIDI_ErrorString = fr._fileName + ": Invalid format, Header signature is unknown!\n"; + errorStringOut = fr._fileName + ": Invalid format, Header signature is unknown!\n"; return false; } @@ -710,7 +710,7 @@ riffskip: if(std::memcmp(HeaderBuf, "MTrk", 4) != 0) { fr.close(); - ADLMIDI_ErrorString = fr._fileName + ": Invalid format, MTrk signature is not found!\n"; + errorStringOut = fr._fileName + ": Invalid format, MTrk signature is not found!\n"; return false; } TrackLength = (size_t)ReadBEint(HeaderBuf + 4, 4); @@ -746,14 +746,14 @@ riffskip: if(totalGotten == 0) { - ADLMIDI_ErrorString = fr._fileName + ": Empty track data"; + errorStringOut = fr._fileName + ": Empty track data"; return false; } //Build new MIDI events table (ALPHA!!!) if(!buildTrackData()) { - ADLMIDI_ErrorString = fr._fileName + ": MIDI data parsing error has occouped!\n" + errorString; + errorStringOut = fr._fileName + ": MIDI data parsing error has occouped!\n" + errorString; return false; } diff --git a/src/adlmidi_midiplay.cpp b/src/adlmidi_midiplay.cpp index fa95e32..7d1ba75 100644 --- a/src/adlmidi_midiplay.cpp +++ b/src/adlmidi_midiplay.cpp @@ -529,9 +529,9 @@ bool MIDIplay::buildTrackData() #if 1 //Use this to record WAVEs for comparison before/after implementing of this if(opl.m_musicMode == OPL3::MODE_MIDI)//Percussion fix is needed for MIDI only, not for IMF/RSXX or CMF { -//! Minimal real time in seconds + //! Minimal real time in seconds #define DRUM_NOTE_MIN_TIME 0.03 -//! Minimal ticks count + //! Minimal ticks count #define DRUM_NOTE_MIN_TICKS 15 struct NoteState { @@ -1778,6 +1778,16 @@ MIDIplay::MidiEvent MIDIplay::parseEvent(uint8_t **pptr, uint8_t *end, int &stat return evt; } +const std::string &MIDIplay::getErrorString() +{ + return errorStringOut; +} + +void MIDIplay::setErrorString(const std::string &err) +{ + errorStringOut = err; +} + void MIDIplay::HandleEvent(size_t tk, MIDIplay::MidiEvent &evt, int &status) { @@ -2323,3 +2333,193 @@ retry_arpeggio: } } } + + +#ifndef ADLMIDI_DISABLE_CPP_EXTRAS + +ADLMIDI_EXPORT AdlInstrumentTester::AdlInstrumentTester(ADL_MIDIPlayer *device) +{ + cur_gm = 0; + ins_idx = 0; + play = reinterpret_cast<MIDIplay *>(device->adl_midiPlayer); + if(!play) + return; + opl = &play->opl; +} + +ADLMIDI_EXPORT AdlInstrumentTester::~AdlInstrumentTester() +{} + +ADLMIDI_EXPORT void AdlInstrumentTester::FindAdlList() +{ + const unsigned NumBanks = (unsigned)adl_getBanksCount(); + std::set<unsigned> adl_ins_set; + for(unsigned bankno = 0; bankno < NumBanks; ++bankno) + adl_ins_set.insert(banks[bankno][cur_gm]); + adl_ins_list.assign(adl_ins_set.begin(), adl_ins_set.end()); + ins_idx = 0; + NextAdl(0); + opl->Silence(); +} + + + +ADLMIDI_EXPORT void AdlInstrumentTester::Touch(unsigned c, unsigned volume) // Volume maxes at 127*127*127 +{ + if(opl->LogarithmicVolumes)// !!!ADL PRIVATE!!! + opl->Touch_Real(c, volume * 127 / (127 * 127 * 127) / 2);// !!!ADL PRIVATE!!! + else + { + // The formula below: SOLVE(V=127^3 * 2^( (A-63.49999) / 8), A) + opl->Touch_Real(c, volume > 8725 ? static_cast<unsigned int>(std::log(volume) * 11.541561 + (0.5 - 104.22845)) : 0);// !!!ADL PRIVATE!!! + // The incorrect formula below: SOLVE(V=127^3 * (2^(A/63)-1), A) + //Touch_Real(c, volume>11210 ? 91.61112 * std::log(4.8819E-7*volume + 1.0)+0.5 : 0); + } +} + +ADLMIDI_EXPORT void AdlInstrumentTester::DoNote(int note) +{ + if(adl_ins_list.empty()) FindAdlList(); + const unsigned meta = adl_ins_list[ins_idx]; + const adlinsdata &ains = opl->GetAdlMetaIns(meta);// !!!ADL PRIVATE!!! + + int tone = (cur_gm & 128) ? (cur_gm & 127) : (note + 50); + if(ains.tone) + { + /*if(ains.tone < 20) + tone += ains.tone; + else */ + if(ains.tone < 128) + tone = ains.tone; + else + tone -= ains.tone - 128; + } + double hertz = 172.00093 * std::exp(0.057762265 * (tone + 0.0)); + int i[2] = { ains.adlno1, ains.adlno2 }; + int32_t adlchannel[2] = { 0, 3 }; + if(i[0] == i[1]) + { + adlchannel[1] = -1; + adlchannel[0] = 6; // single-op + if(play->hooks.onDebugMessage) + { + play->hooks.onDebugMessage(play->hooks.onDebugMessage_userData, + "noteon at %d(%d) for %g Hz\n", adlchannel[0], i[0], hertz); + } + } + else + { + if(play->hooks.onDebugMessage) + { + play->hooks.onDebugMessage(play->hooks.onDebugMessage_userData, + "noteon at %d(%d) and %d(%d) for %g Hz\n", adlchannel[0], i[0], adlchannel[1], i[1], hertz); + } + } + + opl->NoteOff(0); + opl->NoteOff(3); + opl->NoteOff(6); + for(unsigned c = 0; c < 2; ++c) + { + if(adlchannel[c] < 0) continue; + opl->Patch((uint16_t)adlchannel[c], (uint16_t)i[c]); + opl->Touch_Real((uint16_t)adlchannel[c], 127 * 127 * 100); + opl->Pan((uint16_t)adlchannel[c], 0x30); + opl->NoteOn((uint16_t)adlchannel[c], hertz); + } +} + +ADLMIDI_EXPORT void AdlInstrumentTester::NextGM(int offset) +{ + cur_gm = (cur_gm + 256 + (uint32_t)offset) & 0xFF; + FindAdlList(); +} + +ADLMIDI_EXPORT void AdlInstrumentTester::NextAdl(int offset) +{ + if(adl_ins_list.empty()) FindAdlList(); + const unsigned NumBanks = (unsigned)adl_getBanksCount(); + ins_idx = (uint32_t)((int32_t)ins_idx + (int32_t)adl_ins_list.size() + offset) % adl_ins_list.size(); + + #if 0 + UI.Color(15); + std::fflush(stderr); + std::printf("SELECTED G%c%d\t%s\n", + cur_gm < 128 ? 'M' : 'P', cur_gm < 128 ? cur_gm + 1 : cur_gm - 128, + "<-> select GM, ^v select ins, qwe play note"); + std::fflush(stdout); + UI.Color(7); + std::fflush(stderr); + #endif + + for(unsigned a = 0; a < adl_ins_list.size(); ++a) + { + const unsigned i = adl_ins_list[a]; + const adlinsdata &ains = opl->GetAdlMetaIns(i); + + char ToneIndication[8] = " "; + if(ains.tone) + { + /*if(ains.tone < 20) + std::sprintf(ToneIndication, "+%-2d", ains.tone); + else*/ + if(ains.tone < 128) + std::sprintf(ToneIndication, "=%-2d", ains.tone); + else + std::sprintf(ToneIndication, "-%-2d", ains.tone - 128); + } + std::printf("%s%s%s%u\t", + ToneIndication, + ains.adlno1 != ains.adlno2 ? "[2]" : " ", + (ins_idx == a) ? "->" : "\t", + i + ); + + for(unsigned bankno = 0; bankno < NumBanks; ++bankno) + if(banks[bankno][cur_gm] == i) + std::printf(" %u", bankno); + + std::printf("\n"); + } +} + +ADLMIDI_EXPORT bool AdlInstrumentTester::HandleInputChar(char ch) +{ + static const char notes[] = "zsxdcvgbhnjmq2w3er5t6y7ui9o0p"; + // c'd'ef'g'a'bC'D'EF'G'A'Bc'd'e + switch(ch) + { + case '/': + case 'H': + case 'A': + NextAdl(-1); + break; + case '*': + case 'P': + case 'B': + NextAdl(+1); + break; + case '-': + case 'K': + case 'D': + NextGM(-1); + break; + case '+': + case 'M': + case 'C': + NextGM(+1); + break; + case 3: + #if !((!defined(__WIN32__) || defined(__CYGWIN__)) && !defined(__DJGPP__)) + case 27: + #endif + return false; + default: + const char *p = strchr(notes, ch); + if(p && *p) + DoNote((p - notes) - 12); + } + return true; +} + +#endif//ADLMIDI_DISABLE_CPP_EXTRAS diff --git a/src/adlmidi_mus2mid.h b/src/adlmidi_mus2mid.h index c56c359..cc41b87 100644 --- a/src/adlmidi_mus2mid.h +++ b/src/adlmidi_mus2mid.h @@ -24,6 +24,15 @@ #include <stdint.h> +#ifdef __DJGPP__ +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef signed short int16_t; +typedef unsigned short uint16_t; +typedef signed long int32_t; +typedef unsigned long uint32_t; +#endif + #ifdef __cplusplus extern "C" { diff --git a/src/adlmidi_opl3.cpp b/src/adlmidi_opl3.cpp index ed005b1..ce26ba6 100644 --- a/src/adlmidi_opl3.cpp +++ b/src/adlmidi_opl3.cpp @@ -23,6 +23,10 @@ #include "adlmidi_private.hpp" +#ifdef ADLMIDI_HW_OPL +static const unsigned OPLBase = 0x388; +#endif + #ifdef DISABLE_EMBEDDED_BANKS /* Dummy data which replaces adldata.cpp banks database @@ -151,20 +155,38 @@ OPL3::OPL3() : void OPL3::Poke(size_t card, uint32_t index, uint32_t value) { + #ifdef ADLMIDI_HW_OPL + unsigned o = index >> 8; + unsigned port = OPLBase + o * 2; + outportb(port, index); + for(unsigned c = 0; c < 6; ++c) inportb(port); + outportb(port + 1, value); + for(unsigned c = 0; c < 35; ++c) inportb(port); + #else #ifdef ADLMIDI_USE_DOSBOX_OPL cards[card].WriteReg(index, static_cast<uint8_t>(value)); #else OPL3_WriteReg(&cards[card], static_cast<Bit16u>(index), static_cast<Bit8u>(value)); #endif + #endif } void OPL3::PokeN(size_t card, uint16_t index, uint8_t value) { + #ifdef ADLMIDI_HW_OPL + unsigned o = index >> 8; + unsigned port = OPLBase + o * 2; + outportb(port, index); + for(unsigned c = 0; c < 6; ++c) inportb(port); + outportb(port + 1, value); + for(unsigned c = 0; c < 35; ++c) inportb(port); + #else #ifdef ADLMIDI_USE_DOSBOX_OPL cards[card].WriteReg(static_cast<Bit32u>(index), value); #else OPL3_WriteReg(&cards[card], index, value); #endif + #endif } @@ -427,11 +449,15 @@ void OPL3::Reset(unsigned long PCM_RATE) _opl3_chip emptyChip; std::memset(&emptyChip, 0, sizeof(_opl3_chip)); #endif + #ifndef ADLMIDI_HW_OPL cards.clear(); + #endif ins.clear(); pit.clear(); regBD.clear(); + #ifndef ADLMIDI_HW_OPL cards.resize(NumCards, emptyChip); + #endif NumChannels = NumCards * 23; ins.resize(NumChannels, 189); pit.resize(NumChannels, 0); @@ -454,10 +480,12 @@ void OPL3::Reset(unsigned long PCM_RATE) for(unsigned card = 0; card < NumCards; ++card) { - #ifdef ADLMIDI_USE_DOSBOX_OPL + #ifndef ADLMIDI_HW_OPL + # ifdef ADLMIDI_USE_DOSBOX_OPL cards[card].Init(PCM_RATE); - #else + # else OPL3_Reset(&cards[card], static_cast<Bit32u>(PCM_RATE)); + # endif #endif for(unsigned a = 0; a < 18; ++a) Poke(card, 0xB0 + Channels[a], 0x00); diff --git a/src/adlmidi_private.cpp b/src/adlmidi_private.cpp index 04bb481..f13aa8c 100644 --- a/src/adlmidi_private.cpp +++ b/src/adlmidi_private.cpp @@ -65,9 +65,9 @@ int adlRefreshNumCards(ADL_MIDIPlayer *device) if(n_fourop[0] >= n_total[0] * 15 / 16 && play->m_setup.NumFourOps == 0) { - ADLMIDI_ErrorString = "ERROR: You have selected a bank that consists almost exclusively of four-op patches.\n" + play->setErrorString("ERROR: You have selected a bank that consists almost exclusively of four-op patches.\n" " The results (silence + much cpu load) would be probably\n" - " not what you want, therefore ignoring the request.\n"; + " not what you want, therefore ignoring the request.\n"); return -1; } diff --git a/src/adlmidi_private.hpp b/src/adlmidi_private.hpp index 650291a..698dad5 100644 --- a/src/adlmidi_private.hpp +++ b/src/adlmidi_private.hpp @@ -24,29 +24,43 @@ #ifndef ADLMIDI_PRIVATE_HPP #define ADLMIDI_PRIVATE_HPP +#ifndef ADLMIDI_VERSION +#define ADLMIDI_VERSION "1.3.0" +#endif + // Setup compiler defines useful for exporting required public API symbols in gme.cpp #ifndef ADLMIDI_EXPORT - #if defined (_WIN32) && defined(ADLMIDI_BUILD_DLL) - #define ADLMIDI_EXPORT __declspec(dllexport) - #elif defined (LIBADLMIDI_VISIBILITY) - #define ADLMIDI_EXPORT __attribute__((visibility ("default"))) - #else - #define ADLMIDI_EXPORT - #endif +# if defined (_WIN32) && defined(ADLMIDI_BUILD_DLL) +# define ADLMIDI_EXPORT __declspec(dllexport) +# elif defined (LIBADLMIDI_VISIBILITY) +# define ADLMIDI_EXPORT __attribute__((visibility ("default"))) +# else +# define ADLMIDI_EXPORT +# endif #endif #ifdef _WIN32 - #undef NO_OLDNAMES - - #ifdef _MSC_VER - #ifdef _WIN64 - typedef __int64 ssize_t; - #else - typedef __int32 ssize_t; - #endif - #define NOMINMAX //Don't override std::min and std::max - #endif - #include <windows.h> +# undef NO_OLDNAMES + +# ifdef _MSC_VER +# ifdef _WIN64 +typedef __int64 ssize_t; +# else +typedef __int32 ssize_t; +# endif +# define NOMINMAX //Don't override std::min and std::max +# endif +# include <windows.h> +#endif + +#ifdef __DJGPP__ +#define ADLMIDI_HW_OPL +#include <conio.h> +#include <pc.h> +#include <dpmi.h> +#include <go32.h> +#include <sys/farptr.h> +#include <dos.h> #endif #include <vector> @@ -72,15 +86,19 @@ #include <deque> #include <algorithm> -#include "fraction.h" +#include "fraction.hpp" + #ifdef ADLMIDI_USE_DOSBOX_OPL - #include "dbopl.h" +#include "dbopl.h" #else - #include "nukedopl3.h" +#include "nukedopl3.h" #endif #include "adldata.hh" -#include "adlmidi.h" +#include "adlmidi.h" //Main API +#ifndef ADLMIDI_DISABLE_CPP_EXTRAS +#include "adlmidi.hpp" //Extra C++ API +#endif #define ADL_UNUSED(x) (void)x @@ -93,7 +111,7 @@ extern std::string ADLMIDI_ErrorString; template<class PTR> class AdlMIDI_CPtr { - PTR* m_p; + PTR *m_p; public: AdlMIDI_CPtr() : m_p(NULL) {} ~AdlMIDI_CPtr() @@ -108,9 +126,18 @@ public: m_p = p; } - PTR* get() { return m_p;} - PTR& operator*() { return *m_p; } - PTR* operator->() { return m_p; } + PTR *get() + { + return m_p; + } + PTR &operator*() + { + return *m_p; + } + PTR *operator->() + { + return m_p; + } }; class MIDIplay; @@ -120,11 +147,13 @@ struct OPL3 uint32_t NumChannels; char ____padding[4]; ADL_MIDIPlayer *_parent; + #ifndef ADLMIDI_HW_OPL #ifdef ADLMIDI_USE_DOSBOX_OPL std::vector<DBOPL::Handler> cards; #else std::vector<_opl3_chip> cards; #endif + #endif private: std::vector<size_t> ins; // index to adl[], cached, needed by Touch() std::vector<uint8_t> pit; // value poked to B0, cached, needed by NoteOff)( @@ -134,7 +163,7 @@ private: std::vector<adlinsdata> dynamic_metainstruments; // Replaces adlins[] when CMF file std::vector<adldata> dynamic_instruments; // Replaces adl[] when CMF file const unsigned DynamicInstrumentTag /* = 0x8000u*/, - DynamicMetaInstrumentTag /* = 0x4000000u*/; + DynamicMetaInstrumentTag /* = 0x4000000u*/; public: const adlinsdata &GetAdlMetaIns(unsigned n); unsigned GetAdlMetaNumber(unsigned midiins); @@ -540,9 +569,9 @@ public: ST_ENDTRACK = 0x2F,//size == 0 ST_TEMPOCHANGE = 0x51,//size == 3 ST_SMPTEOFFSET = 0x54,//size == 5 - ST_TIMESIGNATURE= 0x55,//size == 4 + ST_TIMESIGNATURE = 0x55, //size == 4 ST_KEYSIGNATURE = 0x59,//size == 2 - ST_SEQUENCERSPEC= 0x7F,//size == len + ST_SEQUENCERSPEC = 0x7F, //size == len /* Non-standard, internal ADLMIDI usage only */ ST_LOOPSTART = 0xE1,//size == 0 <CUSTOM> @@ -690,6 +719,8 @@ private: double loopEndTime; //! Local error string std::string errorString; + //! Local error string + std::string errorStringOut; //! Pre-processed track data storage std::vector<MidiTrackQueue > trackDataNew; @@ -714,6 +745,9 @@ private: public: + const std::string &getErrorString(); + void setErrorString(const std::string &err); + std::string musTitle; std::string musCopyright; std::vector<std::string> musTrackTitles; diff --git a/src/adlmidi_xmi2mid.h b/src/adlmidi_xmi2mid.h index 523e8d7..950d58c 100644 --- a/src/adlmidi_xmi2mid.h +++ b/src/adlmidi_xmi2mid.h @@ -27,6 +27,15 @@ #include <stdint.h> +#ifdef __DJGPP__ +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef signed short int16_t; +typedef unsigned short uint16_t; +typedef signed long int32_t; +typedef unsigned long uint32_t; +#endif + #ifdef __cplusplus extern "C" { diff --git a/src/fraction.h b/src/fraction.hpp index 1ec10ab..1ec10ab 100644 --- a/src/fraction.h +++ b/src/fraction.hpp |