aboutsummaryrefslogtreecommitdiff
path: root/src/adlmidi.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/adlmidi.cpp')
-rw-r--r--src/adlmidi.cpp277
1 files changed, 53 insertions, 224 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