diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/adlmidi.cpp | 277 | ||||
-rw-r--r-- | src/adlmidi.h | 4 | ||||
-rw-r--r-- | src/adlmidi_load.cpp | 23 | ||||
-rw-r--r-- | src/adlmidi_midiplay.cpp | 89 | ||||
-rw-r--r-- | src/adlmidi_opl3.cpp | 24 | ||||
-rw-r--r-- | src/adlmidi_private.hpp | 7 | ||||
-rw-r--r-- | src/midiplay/adlmidiplay.cpp | 83 |
7 files changed, 209 insertions, 298 deletions
diff --git a/src/adlmidi.cpp b/src/adlmidi.cpp index 79c1422..11b7c9b 100644 --- a/src/adlmidi.cpp +++ b/src/adlmidi.cpp @@ -23,52 +23,47 @@ #include "adlmidi_private.hpp" -#ifdef ADLMIDI_buildAsApp -#define SDL_MAIN_HANDLED -#include <SDL2/SDL.h> -#endif - static const unsigned MaxCards = 100; /*---------------------------EXPORTS---------------------------*/ ADLMIDI_EXPORT struct ADL_MIDIPlayer *adl_init(long sample_rate) { - ADL_MIDIPlayer *_device; - _device = (ADL_MIDIPlayer *)malloc(sizeof(ADL_MIDIPlayer)); - _device->PCM_RATE = static_cast<unsigned long>(sample_rate); - _device->AdlBank = 0; - _device->NumFourOps = 7; - _device->NumCards = 2; - _device->HighTremoloMode = 0; - _device->HighVibratoMode = 0; - _device->AdlPercussionMode = 0; - _device->LogarithmicVolumes = 0; - _device->QuitFlag = 0; - _device->SkipForward = 0; - _device->QuitWithoutLooping = 0; - _device->ScaleModulators = 0; - _device->delay = 0.0; - _device->carry = 0.0; - _device->mindelay = 1.0 / (double)_device->PCM_RATE; - _device->maxdelay = 512.0 / (double)_device->PCM_RATE; - _device->stored_samples = 0; - _device->backup_samples_size = 0; + ADL_MIDIPlayer *midi_device; + midi_device = (ADL_MIDIPlayer *)malloc(sizeof(ADL_MIDIPlayer)); + midi_device->PCM_RATE = static_cast<unsigned long>(sample_rate); + midi_device->AdlBank = 0; + midi_device->NumFourOps = 7; + midi_device->NumCards = 2; + midi_device->HighTremoloMode = 0; + midi_device->HighVibratoMode = 0; + midi_device->AdlPercussionMode = 0; + midi_device->LogarithmicVolumes = 0; + midi_device->SkipForward = 0; + midi_device->QuitWithoutLooping = 0; + midi_device->ScaleModulators = 0; + midi_device->delay = 0.0; + midi_device->carry = 0.0; + midi_device->mindelay = 1.0 / (double)midi_device->PCM_RATE; + midi_device->maxdelay = 512.0 / (double)midi_device->PCM_RATE; + midi_device->stored_samples = 0; + midi_device->backup_samples_size = 0; + MIDIplay *player = new MIDIplay; - _device->adl_midiPlayer = player; - player->config = _device; - player->opl._parent = _device; - player->opl.NumCards = _device->NumCards; - player->opl.AdlBank = _device->AdlBank; - player->opl.NumFourOps = _device->NumFourOps; - player->opl.LogarithmicVolumes = (bool)_device->LogarithmicVolumes; - player->opl.HighTremoloMode = (bool)_device->HighTremoloMode; - player->opl.HighVibratoMode = (bool)_device->HighVibratoMode; - player->opl.AdlPercussionMode = (bool)_device->AdlPercussionMode; - player->opl.ScaleModulators = (bool)_device->ScaleModulators; + midi_device->adl_midiPlayer = player; + player->config = midi_device; + player->opl._parent = midi_device; + player->opl.NumCards = midi_device->NumCards; + player->opl.AdlBank = midi_device->AdlBank; + player->opl.NumFourOps = midi_device->NumFourOps; + player->opl.LogarithmicVolumes = (bool)midi_device->LogarithmicVolumes; + player->opl.HighTremoloMode = (bool)midi_device->HighTremoloMode; + player->opl.HighVibratoMode = (bool)midi_device->HighVibratoMode; + player->opl.AdlPercussionMode = (bool)midi_device->AdlPercussionMode; + player->opl.ScaleModulators = (bool)midi_device->ScaleModulators; player->ChooseDevice("none"); - adlRefreshNumCards(_device); - return _device; + adlRefreshNumCards(midi_device); + return midi_device; } ADLMIDI_EXPORT int adl_setNumCards(ADL_MIDIPlayer *device, int numCards) @@ -92,6 +87,12 @@ ADLMIDI_EXPORT int adl_setNumCards(ADL_MIDIPlayer *device, int numCards) ADLMIDI_EXPORT int adl_setBank(ADL_MIDIPlayer *device, int bank) { + #ifdef DISABLE_EMBEDDED_BANKS + ADL_UNUSED(device); + ADL_UNUSED(bank); + ADLMIDI_ErrorString = "This build of libADLMIDI has no embedded banks. Please load bank by using of adl_openBankFile() or adl_openBankData() functions instead of adl_setBank()"; + return -1; + #else const uint32_t NumBanks = static_cast<uint32_t>(maxAdlBanks()); int32_t bankno = bank; @@ -99,7 +100,8 @@ ADLMIDI_EXPORT int adl_setBank(ADL_MIDIPlayer *device, int bank) bankno = 0; device->AdlBank = static_cast<uint32_t>(bankno); - reinterpret_cast<MIDIplay *>(device->adl_midiPlayer)->opl.AdlBank = device->AdlBank; + MIDIplay *play = reinterpret_cast<MIDIplay *>(device->adl_midiPlayer); + play->opl.AdlBank = device->AdlBank; if(device->AdlBank >= NumBanks) { @@ -110,6 +112,7 @@ ADLMIDI_EXPORT int adl_setBank(ADL_MIDIPlayer *device, int bank) } return adlRefreshNumCards(device); + #endif } ADLMIDI_EXPORT int adl_getBanksCount() @@ -317,6 +320,14 @@ ADLMIDI_EXPORT void adl_reset(ADL_MIDIPlayer *device) reinterpret_cast<MIDIplay *>(device->adl_midiPlayer)->opl.Reset(); } +ADLMIDI_EXPORT void adl_positionRewind(struct ADL_MIDIPlayer *device) +{ + if(!device) + return; + reinterpret_cast<MIDIplay *>(device->adl_midiPlayer)->rewind(); +} + + #ifdef ADLMIDI_USE_DOSBOX_OPL #define ADLMIDI_CLAMP(V, MIN, MAX) std::max(std::min(V, (MAX)), (MIN)) @@ -393,9 +404,6 @@ ADLMIDI_EXPORT int adl_play(ADL_MIDIPlayer *device, int sampleCount, short *out) if(sampleCount < 0) return 0; - if(device->QuitFlag) - return 0; - ssize_t gotten_len = 0; ssize_t n_periodCountStereo = 512; //ssize_t n_periodCountPhys = n_periodCountStereo * 2; @@ -446,6 +454,9 @@ ADLMIDI_EXPORT int adl_play(ADL_MIDIPlayer *device, int sampleCount, short *out) out_buf.resize(1024 /*n_samples * 2*/); MIDIplay *player = reinterpret_cast<MIDIplay *>(device->adl_midiPlayer); + if((player->atEnd) && (device->delay <= 0.0)) + break;//Stop to fetch samples at reaching of song end with disabled loop + ssize_t in_generatedStereo = (n_periodCountStereo > 512) ? 512 : n_periodCountStereo; ssize_t in_generatedPhys = in_generatedStereo * 2; @@ -500,185 +511,3 @@ ADLMIDI_EXPORT int adl_play(ADL_MIDIPlayer *device, int sampleCount, short *out) return static_cast<int>(gotten_len); } - -#ifdef ADLMIDI_buildAsApp -static std::deque<short> AudioBuffer; -static MutexType AudioBuffer_lock; - -static void SDL_AudioCallbackX(void *, Uint8 *stream, int len) -{ - SDL_LockAudio(); - short *target = (short *) stream; - AudioBuffer_lock.Lock(); - /*if(len != AudioBuffer.size()) - fprintf(stderr, "len=%d stereo samples, AudioBuffer has %u stereo samples", - len/4, (unsigned) AudioBuffer.size()/2);*/ - unsigned ate = len / 2; // number of shorts - - if(ate > AudioBuffer.size()) ate = AudioBuffer.size(); - - for(unsigned a = 0; a < ate; ++a) - target[a] = AudioBuffer[a]; - - AudioBuffer.erase(AudioBuffer.begin(), AudioBuffer.begin() + ate); - AudioBuffer_lock.Unlock(); - SDL_UnlockAudio(); -} - -int main(int argc, char **argv) -{ - if(argc < 2 || std::string(argv[1]) == "--help" || std::string(argv[1]) == "-h") - { - std::printf( - "Usage: adlmidi <midifilename> [ <options> ] [ <banknumber> [ <numcards> [ <numfourops>] ] ]\n" - " -p Enables adlib percussion instrument mode\n" - " -t Enables tremolo amplification mode\n" - " -v Enables vibrato amplification mode\n" - " -s Enables scaling of modulator volumes\n" - " -nl Quit without looping\n" - " -w Write WAV file rather than playing\n" - ); - - for(unsigned a = 0; a < sizeof(banknames) / sizeof(*banknames); ++a) - std::printf("%10s%2u = %s\n", - a ? "" : "Banks:", - a, - banknames[a]); - - std::printf( - " Use banks 2-5 to play Descent \"q\" soundtracks.\n" - " Look up the relevant bank number from descent.sng.\n" - "\n" - " The fourth parameter can be used to specify the number\n" - " of four-op channels to use. Each four-op channel eats\n" - " the room of two regular channels. Use as many as required.\n" - " The Doom & Hexen sets require one or two, while\n" - " Miles four-op set requires the maximum of numcards*6.\n" - "\n" - ); - return 0; - } - - //const unsigned MaxSamplesAtTime = 512; // 512=dbopl limitation - // How long is SDL buffer, in seconds? - // The smaller the value, the more often SDL_AudioCallBack() - // is called. - const double AudioBufferLength = 0.08; - // How much do WE buffer, in seconds? The smaller the value, - // the more prone to sound chopping we are. - const double OurHeadRoomLength = 0.1; - // The lag between visual content and audio content equals - // the sum of these two buffers. - SDL_AudioSpec spec; - SDL_AudioSpec obtained; - spec.freq = 44100; - spec.format = AUDIO_S16SYS; - spec.channels = 2; - spec.samples = spec.freq * AudioBufferLength; - spec.callback = SDL_AudioCallbackX; - - // Set up SDL - if(SDL_OpenAudio(&spec, &obtained) < 0) - { - std::fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError()); - //return 1; - } - - if(spec.samples != obtained.samples) - std::fprintf(stderr, "Wanted (samples=%u,rate=%u,channels=%u); obtained (samples=%u,rate=%u,channels=%u)\n", - spec.samples, spec.freq, spec.channels, - obtained.samples, obtained.freq, obtained.channels); - - ADL_MIDIPlayer *myDevice; - myDevice = adl_init(44100); - - if(myDevice == NULL) - { - std::fprintf(stderr, "Failed to init MIDI device!\n"); - return 1; - } - - while(argc > 2) - { - bool had_option = false; - - if(!std::strcmp("-p", argv[2])) - adl_setPercMode(myDevice, 1); - else if(!std::strcmp("-v", argv[2])) - adl_setHVibrato(myDevice, 1); - else if(!std::strcmp("-t", argv[2])) - adl_setHTremolo(myDevice, 1); - else if(!std::strcmp("-nl", argv[2])) - adl_setLoopEnabled(myDevice, 0); - else if(!std::strcmp("-s", argv[2])) - adl_setScaleModulators(myDevice, 1); - else break; - - std::copy(argv + (had_option ? 4 : 3), argv + argc, - argv + 2); - argc -= (had_option ? 2 : 1); - } - - if(argc >= 3) - { - int bankno = std::atoi(argv[2]); - - if(adl_setBank(myDevice, bankno) != 0) - { - std::fprintf(stderr, "%s", adl_errorString()); - return 0; - } - } - - if(argc >= 4) - { - if(adl_setNumCards(myDevice, std::atoi(argv[3])) != 0) - { - std::fprintf(stderr, "%s\n", adl_errorString()); - return 0; - } - } - - if(argc >= 5) - { - if(adl_setNumFourOpsChn(myDevice, std::atoi(argv[4])) != 0) - { - std::fprintf(stderr, "%s\n", adl_errorString()); - return 0; - } - } - - if(adl_openFile(myDevice, argv[1]) != 0) - { - std::fprintf(stderr, "%s\n", adl_errorString()); - return 2; - } - - SDL_PauseAudio(0); - - while(1) - { - int buff[4096]; - unsigned long gotten = adl_play(myDevice, 4096, buff); - - if(gotten <= 0) break; - - AudioBuffer_lock.Lock(); - size_t pos = AudioBuffer.size(); - AudioBuffer.resize(pos + gotten); - - for(unsigned long p = 0; p < gotten; ++p) - AudioBuffer[pos + p] = buff[p]; - - AudioBuffer_lock.Unlock(); - const SDL_AudioSpec &spec_ = obtained; - - while(AudioBuffer.size() > spec_.samples + (spec_.freq * 2) * OurHeadRoomLength) - SDL_Delay(1); - } - - adl_close(myDevice); - SDL_CloseAudio(); - return 0; -} -#endif diff --git a/src/adlmidi.h b/src/adlmidi.h index 752e307..5aa913b 100644 --- a/src/adlmidi.h +++ b/src/adlmidi.h @@ -48,7 +48,6 @@ struct ADL_MIDIPlayer unsigned int AdlPercussionMode; unsigned int LogarithmicVolumes; int VolumeModel; - unsigned int QuitFlag; unsigned int SkipForward; unsigned int QuitWithoutLooping; unsigned int ScaleModulators; @@ -128,6 +127,9 @@ extern int adl_openData(struct ADL_MIDIPlayer *device, void *mem, long size); /*Resets MIDI player*/ extern void adl_reset(struct ADL_MIDIPlayer *device); +/*Reset MIDI track position to begin */ +extern void adl_positionRewind(struct ADL_MIDIPlayer *device); + /*Close and delete ADLMIDI device*/ extern void adl_close(struct ADL_MIDIPlayer *device); diff --git a/src/adlmidi_load.cpp b/src/adlmidi_load.cpp index 5258dc9..a1242d7 100644 --- a/src/adlmidi_load.cpp +++ b/src/adlmidi_load.cpp @@ -200,9 +200,8 @@ static bool readInstrument(MIDIplay::fileReader &file, WOPL_Inst &ins, bool isPe bool MIDIplay::LoadBank(MIDIplay::fileReader &fr) { -#define qqq(x) (void)x size_t fsize; - qqq(fsize); + ADL_UNUSED(fsize); if(!fr.isValid()) { ADLMIDI_ErrorString = "Custom bank: Invalid data stream!"; @@ -296,6 +295,7 @@ bool MIDIplay::LoadBank(MIDIplay::fileReader &fr) } } + opl.AdlBank = opl._parent->AdlBank; opl.dynamic_metainstruments.clear(); opl.dynamic_instruments.clear(); @@ -351,10 +351,7 @@ bool MIDIplay::LoadMIDI(const std::string &filename) file.openFile(filename.c_str()); if(!LoadMIDI(file)) - { - std::perror(filename.c_str()); return false; - } return true; } @@ -368,16 +365,23 @@ bool MIDIplay::LoadMIDI(void *data, unsigned long size) bool MIDIplay::LoadMIDI(MIDIplay::fileReader &fr) { -#define qqq(x) (void)x size_t fsize; - qqq(fsize); + ADL_UNUSED(fsize); //! Temp buffer for conversion AdlMIDI_CPtr<uint8_t> cvt_buf; - //std::FILE* fr = std::fopen(filename.c_str(), "rb"); + #ifdef DISABLE_EMBEDDED_BANKS + if((opl.AdlBank != ~0u) || (opl.dynamic_metainstruments.size() < 256)) + { + ADLMIDI_ErrorString = "Bank is not set! Please load any instruments bank by using of adl_openBankFile() or adl_openBankData() functions!"; + return false; + } + #endif + if(!fr.isValid()) { - ADLMIDI_ErrorString = "Invalid data stream!"; + ADLMIDI_ErrorString = "Invalid data stream!\n"; + ADLMIDI_ErrorString += std::strerror(errno); return false; } @@ -429,6 +433,7 @@ bool MIDIplay::LoadMIDI(MIDIplay::fileReader &fr) opl.Reset(); trackStart = true; + atEnd = false; loopStart = true; loopStart_passed = false; invalidLoop = false; diff --git a/src/adlmidi_midiplay.cpp b/src/adlmidi_midiplay.cpp index 24dd60f..3b9d396 100644 --- a/src/adlmidi_midiplay.cpp +++ b/src/adlmidi_midiplay.cpp @@ -133,6 +133,7 @@ MIDIplay::MIDIplay(): cmf_percussion_mode(false), config(NULL), trackStart(false), + atEnd(false), loopStart(false), loopEnd(false), loopStart_passed(false), @@ -163,20 +164,18 @@ double MIDIplay::Tick(double s, double granularity) if(CurrentPosition.began) CurrentPosition.wait -= s; - int AntiFreezeCounter = 10000;//Limit 10000 loops to avoid freezing - - while((CurrentPosition.wait <= granularity * 0.5) && (AntiFreezeCounter > 0)) + int antiFreezeCounter = 10000;//Limit 10000 loops to avoid freezing + while((CurrentPosition.wait <= granularity * 0.5) && (antiFreezeCounter > 0)) { //std::fprintf(stderr, "wait = %g...\n", CurrentPosition.wait); - ProcessEvents(); - + if(!ProcessEvents()) + break; if(CurrentPosition.wait <= 0.0) - AntiFreezeCounter--; + antiFreezeCounter--; } - if(AntiFreezeCounter <= 0) + if(antiFreezeCounter <= 0) CurrentPosition.wait += 1.0;/* Add extra 1 second when over 10000 events - with zero delay are been detected */ for(uint16_t c = 0; c < opl.NumChannels; ++c) @@ -184,9 +183,21 @@ double MIDIplay::Tick(double s, double granularity) UpdateVibrato(s); UpdateArpeggio(s); + return CurrentPosition.wait; } +void MIDIplay::rewind() +{ + CurrentPosition = trackBeginPosition; + trackStart = true; + atEnd = false; + loopStart = true; + loopStart_passed = false; + invalidLoop = false; + loopStart_hit = false; +} + void MIDIplay::realTime_ResetState() { for(size_t ch = 0; ch < Ch.size(); ch++) @@ -358,7 +369,7 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity) } } - long s = CalculateAdlChannelGoodness(a, i[ccount], channel ); + long s = CalculateAdlChannelGoodness(a, i[ccount], channel); if(s > bs) { @@ -809,8 +820,13 @@ void MIDIplay::NoteUpdate(uint16_t MidCh, } -void MIDIplay::ProcessEvents() +bool MIDIplay::ProcessEvents() { + if(TrackData.size() == 0) + atEnd = true;//No MIDI track data to play + if(atEnd) + return false;//No more events in the queue + loopEnd = false; const size_t TrackCount = TrackData.size(); const Position RowBeginPosition(CurrentPosition); @@ -877,6 +893,7 @@ void MIDIplay::ProcessEvents() { trackBeginPosition = RowBeginPosition; trackStart = false; + atEnd = false; } LoopBeginPosition = RowBeginPosition; loopStart = false; @@ -885,16 +902,19 @@ void MIDIplay::ProcessEvents() if(shortest_no || loopEnd) { - // Loop if song end reached + //Loop if song end or loop end point has reached loopEnd = false; - CurrentPosition = LoopBeginPosition; shortest = 0; - if(opl._parent->QuitWithoutLooping == 1) + if(opl._parent->QuitWithoutLooping != 0) { - opl._parent->QuitFlag = 1; - //^ HACK: QUIT WITHOUT LOOPING + atEnd = true; //Don't handle events anymore + CurrentPosition.wait += 1.0;//One second delay until stop playing + return true;//We have caugh end here! } + CurrentPosition = LoopBeginPosition; } + + return true;//Has events in queue } void MIDIplay::HandleEvent(size_t tk) @@ -932,25 +952,29 @@ void MIDIplay::HandleEvent(size_t tk) if(evtype == 6) { - /* Move this away from events handler */ - for(size_t i = 0; i < data.size(); i++) + //Turn on/off Loop handling + if(opl._parent->QuitWithoutLooping == 0) { - if(data[i] <= 'Z' && data[i] >= 'A') - data[i] = data[i] - ('Z' - 'z'); - } + /* Move this away from events handler */ + for(size_t i = 0; i < data.size(); i++) + { + if(data[i] <= 'Z' && data[i] >= 'A') + data[i] = data[i] - ('Z' - 'z'); + } - if((data == "loopstart") && (!invalidLoop)) - { - loopStart = true; - loopStart_passed = true; - } + if((data == "loopstart") && (!invalidLoop)) + { + loopStart = true; + loopStart_passed = true; + } - if((data == "loopend") && (!invalidLoop)) - { - if((loopStart_passed) && (!loopStart)) - loopEnd = true; - else - invalidLoop = true; + if((data == "loopend") && (!invalidLoop)) + { + if((loopStart_passed) && (!loopStart)) + loopEnd = true; + else + invalidLoop = true; + } } } @@ -1034,12 +1058,13 @@ void MIDIplay::HandleEvent(size_t tk) uint8_t ctrlno = TrackData[tk][CurrentPosition.track[tk].ptr++]; uint8_t value = TrackData[tk][CurrentPosition.track[tk].ptr++]; - if((ctrlno == 111) && !invalidLoop) + if((opl._parent->QuitWithoutLooping == 0) && (ctrlno == 111) && !invalidLoop) { loopStart = true; loopStart_passed = true; break; } + realTime_Controller(MidCh, ctrlno, value); break; } diff --git a/src/adlmidi_opl3.cpp b/src/adlmidi_opl3.cpp index 7ae2486..d03b942 100644 --- a/src/adlmidi_opl3.cpp +++ b/src/adlmidi_opl3.cpp @@ -23,6 +23,30 @@ #include "adlmidi_private.hpp" +#ifdef DISABLE_EMBEDDED_BANKS +/* + Dummy data which replaces adldata.cpp banks database +*/ + +const struct adldata adl[] +{ + {0, 0, 0, 0, 0, 0} +}; + +const struct adlinsdata adlins[] = +{ + {0, 0, 0, 0, 0, 0, 0.0} +}; + +int maxAdlBanks() +{ + return 0; +} + +const unsigned short banks[][256] = {{0}}; +const char* const banknames[] = {"<Embedded banks are disabled>"}; +#endif + static const unsigned short Operators[23 * 2] = { // Channels 0-2 diff --git a/src/adlmidi_private.hpp b/src/adlmidi_private.hpp index 7bb5774..e039f85 100644 --- a/src/adlmidi_private.hpp +++ b/src/adlmidi_private.hpp @@ -75,6 +75,8 @@ #include "adldata.hh" #include "adlmidi.h" +#define ADL_UNUSED(x) (void)x + extern std::string ADLMIDI_ErrorString; /* @@ -299,6 +301,7 @@ public: std::string musTitle; fraction<uint64_t> InvDeltaTicks, Tempo; bool trackStart, + atEnd, loopStart, loopEnd, loopStart_passed /*Tells that "loopStart" already passed*/, @@ -470,6 +473,8 @@ public: */ double Tick(double s, double granularity); + void rewind(); + /* RealTime event triggers */ void realTime_ResetState(); @@ -505,7 +510,7 @@ private: MIDIchannel::activenoteiterator i, unsigned props_mask, int32_t select_adlchn = -1); - void ProcessEvents(); + bool ProcessEvents(); void HandleEvent(size_t tk); // Determine how good a candidate this adlchannel diff --git a/src/midiplay/adlmidiplay.cpp b/src/midiplay/adlmidiplay.cpp index 0cefb7c..cbea468 100644 --- a/src/midiplay/adlmidiplay.cpp +++ b/src/midiplay/adlmidiplay.cpp @@ -58,6 +58,12 @@ static bool is_number(const std::string &s) return !s.empty() && it == s.end(); } +static void printError(const char *err) +{ + std::fprintf(stderr, "\nERROR: %s\n\n", err); + std::fflush(stderr); +} + #undef main int main(int argc, char **argv) { @@ -83,23 +89,29 @@ int main(int argc, char **argv) int banksCount = adl_getBanksCount(); const char* const* banknames = adl_getBankNames(); - std::printf(" Available embedded banks by number:\n\n"); + if(banksCount > 0) + { + std::printf(" Available embedded banks by number:\n\n"); - for(int a = 0; a < banksCount; ++a) - std::printf("%10s%2u = %s\n", a ? "" : "Banks:", a, banknames[a]); + for(int a = 0; a < banksCount; ++a) + std::printf("%10s%2u = %s\n", a ? "" : "Banks:", a, banknames[a]); + + std::printf( + "\n" + " Use banks 2-5 to play Descent \"q\" soundtracks.\n" + " Look up the relevant bank number from descent.sng.\n" + "\n" + " The fourth parameter can be used to specify the number\n" + " of four-op channels to use. Each four-op channel eats\n" + " the room of two regular channels. Use as many as required.\n" + " The Doom & Hexen sets require one or two, while\n" + " Miles four-op set requires the maximum of numcards*6.\n" + "\n" + ); + } else { + std::printf(" This build of libADLMIDI has no embedded banks!\n\n"); + } - std::printf( - "\n" - " Use banks 2-5 to play Descent \"q\" soundtracks.\n" - " Look up the relevant bank number from descent.sng.\n" - "\n" - " The fourth parameter can be used to specify the number\n" - " of four-op channels to use. Each four-op channel eats\n" - " the room of two regular channels. Use as many as required.\n" - " The Doom & Hexen sets require one or two, while\n" - " Miles four-op set requires the maximum of numcards*6.\n" - "\n" - ); return 0; } @@ -119,13 +131,13 @@ int main(int argc, char **argv) spec.freq = 44100; spec.format = AUDIO_S16SYS; spec.channels = 2; - spec.samples = spec.freq * AudioBufferLength; + spec.samples = Uint16((double)spec.freq * AudioBufferLength); spec.callback = SDL_AudioCallbackX; // Set up SDL if(SDL_OpenAudio(&spec, &obtained) < 0) { - std::fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError()); + std::fprintf(stderr, "\nERROR: Couldn't open audio: %s\n\n", SDL_GetError()); //return 1; } if(spec.samples != obtained.samples) @@ -137,7 +149,7 @@ int main(int argc, char **argv) myDevice = adl_init(44100); if(myDevice == NULL) { - std::fprintf(stderr, "Failed to init MIDI device!\n"); + printError("Failed to init MIDI device!\n"); return 1; } @@ -170,8 +182,7 @@ int main(int argc, char **argv) int bankno = std::atoi(argv[2]); if(adl_setBank(myDevice, bankno) != 0) { - std::fprintf(stderr, "%s\n", adl_errorString()); - std::fflush(stderr); + printError(adl_errorString()); return 0; } } @@ -183,8 +194,7 @@ int main(int argc, char **argv) { std::fprintf(stdout, "FAILED!\n"); std::fflush(stdout); - std::fprintf(stderr, "%s\n", adl_errorString()); - std::fflush(stderr); + printError(adl_errorString()); return 0; } std::fprintf(stdout, "OK!\n"); @@ -196,16 +206,26 @@ int main(int argc, char **argv) { if(adl_setNumCards(myDevice, std::atoi(argv[3])) != 0) { - std::fprintf(stderr, "%s\n", adl_errorString()); + printError(adl_errorString()); return 0; } std::fprintf(stdout, "Number of cards %s\n", argv[3]); } + else + { + // 4 chips by default + if(adl_setNumCards(myDevice, 4) != 0) + { + printError(adl_errorString()); + return 0; + } + } + if(argc >= 5) { if(adl_setNumFourOpsChn(myDevice, std::atoi(argv[4])) != 0) { - std::fprintf(stderr, "%s\n", adl_errorString()); + printError(adl_errorString()); return 0; } std::fprintf(stdout, "Number of four-ops %s\n", argv[4]); @@ -213,7 +233,7 @@ int main(int argc, char **argv) if(adl_openFile(myDevice, argv[1]) != 0) { - std::fprintf(stderr, "%s\n", adl_errorString()); + printError(adl_errorString()); return 2; } @@ -222,18 +242,19 @@ int main(int argc, char **argv) while(1) { short buff[4096]; - unsigned long gotten = adl_play(myDevice, 4096, buff); - if(gotten <= 0) break; + size_t got = (size_t)adl_play(myDevice, 4096, buff); + if(got <= 0) + break; AudioBuffer_lock.Lock(); size_t pos = AudioBuffer.size(); - AudioBuffer.resize(pos + gotten); - for(unsigned long p = 0; p < gotten; ++p) + AudioBuffer.resize(pos + got); + for(size_t p = 0; p < got; ++p) AudioBuffer[pos + p] = buff[p]; AudioBuffer_lock.Unlock(); - const SDL_AudioSpec &spec_ = obtained; - while(AudioBuffer.size() > spec_.samples + (spec_.freq * 2) * OurHeadRoomLength) + const SDL_AudioSpec &spec = obtained; + while(AudioBuffer.size() > spec.samples + (spec.freq * 2) * OurHeadRoomLength) { SDL_Delay(1); } |