358 |
this->MaxSamplesPerCycle = pAudioOutputDevice->MaxSamplesPerCycle(); |
this->MaxSamplesPerCycle = pAudioOutputDevice->MaxSamplesPerCycle(); |
359 |
this->SampleRate = pAudioOutputDevice->SampleRate(); |
this->SampleRate = pAudioOutputDevice->SampleRate(); |
360 |
|
|
361 |
// FIXME: audio drivers with varying fragment sizes might be a problem here |
MinFadeOutSamples = int(double(SampleRate) * CONFIG_EG_MIN_RELEASE_TIME) - 1; |
362 |
MaxFadeOutPos = MaxSamplesPerCycle - int(double(SampleRate) * CONFIG_EG_MIN_RELEASE_TIME) - 1; |
if (MaxSamplesPerCycle < MinFadeOutSamples) { |
|
if (MaxFadeOutPos < 0) { |
|
363 |
std::cerr << "gig::Engine: WARNING, CONFIG_EG_MIN_RELEASE_TIME " |
std::cerr << "gig::Engine: WARNING, CONFIG_EG_MIN_RELEASE_TIME " |
364 |
<< "too big for current audio fragment size & sampling rate! " |
<< "too big for current audio fragment size & sampling rate! " |
365 |
<< "May lead to click sounds if voice stealing chimes in!\n" << std::flush; |
<< "May lead to click sounds if voice stealing chimes in!\n" << std::flush; |
366 |
// force volume ramp downs at the beginning of each fragment |
// force volume ramp downs at the beginning of each fragment |
367 |
MaxFadeOutPos = 0; |
MinFadeOutSamples = MaxSamplesPerCycle; |
368 |
// lower minimum release time |
// lower minimum release time |
369 |
const float minReleaseTime = (float) MaxSamplesPerCycle / (float) SampleRate; |
const float minReleaseTime = (float) MaxSamplesPerCycle / (float) SampleRate; |
370 |
for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) { |
for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) { |
1727 |
//TODO: not sample accurate yet |
//TODO: not sample accurate yet |
1728 |
pEngineChannel->GlobalPanLeft = PanCurve[128 - itControlChangeEvent->Param.CC.Value]; |
pEngineChannel->GlobalPanLeft = PanCurve[128 - itControlChangeEvent->Param.CC.Value]; |
1729 |
pEngineChannel->GlobalPanRight = PanCurve[itControlChangeEvent->Param.CC.Value]; |
pEngineChannel->GlobalPanRight = PanCurve[itControlChangeEvent->Param.CC.Value]; |
1730 |
|
pEngineChannel->iLastPanRequest = itControlChangeEvent->Param.CC.Value; |
1731 |
break; |
break; |
1732 |
} |
} |
1733 |
case 64: { // sustain |
case 64: { // sustain |
1890 |
if (exclusive_status != 0xF0) goto free_sysex_data; |
if (exclusive_status != 0xF0) goto free_sysex_data; |
1891 |
|
|
1892 |
switch (id) { |
switch (id) { |
1893 |
|
case 0x7f: { // (Realtime) Universal Sysex (GM Standard) |
1894 |
|
uint8_t sysex_channel, sub_id1, sub_id2, val_msb, val_lsb;; |
1895 |
|
if (!reader.pop(&sysex_channel)) goto free_sysex_data; |
1896 |
|
if (!reader.pop(&sub_id1)) goto free_sysex_data; |
1897 |
|
if (!reader.pop(&sub_id2)) goto free_sysex_data; |
1898 |
|
if (!reader.pop(&val_lsb)) goto free_sysex_data; |
1899 |
|
if (!reader.pop(&val_msb)) goto free_sysex_data; |
1900 |
|
//TODO: for now we simply ignore the sysex channel, seldom used anyway |
1901 |
|
switch (sub_id1) { |
1902 |
|
case 0x04: // Device Control |
1903 |
|
switch (sub_id2) { |
1904 |
|
case 0x01: // Master Volume |
1905 |
|
GLOBAL_VOLUME = |
1906 |
|
double((uint(val_msb)<<7) | uint(val_lsb)) / 16383.0; |
1907 |
|
break; |
1908 |
|
} |
1909 |
|
break; |
1910 |
|
} |
1911 |
|
break; |
1912 |
|
} |
1913 |
case 0x41: { // Roland |
case 0x41: { // Roland |
1914 |
dmsg(3,("Roland Sysex\n")); |
dmsg(3,("Roland Sysex\n")); |
1915 |
uint8_t device_id, model_id, cmd_id; |
uint8_t device_id, model_id, cmd_id; |
1946 |
dmsg(3,("\t\t\tNew scale applied.\n")); |
dmsg(3,("\t\t\tNew scale applied.\n")); |
1947 |
break; |
break; |
1948 |
} |
} |
1949 |
|
case 0x15: { // chromatic / drumkit mode |
1950 |
|
dmsg(3,("\t\tMIDI Instrument Map Switch\n")); |
1951 |
|
uint8_t part = addr[1] & 0x0f; |
1952 |
|
uint8_t map; |
1953 |
|
if (!reader.pop(&map)) goto free_sysex_data; |
1954 |
|
for (int i = 0; i < engineChannels.size(); ++i) { |
1955 |
|
EngineChannel* pEngineChannel = engineChannels[i]; |
1956 |
|
if (pEngineChannel->midiChannel == part || |
1957 |
|
pEngineChannel->midiChannel == midi_chan_all |
1958 |
|
) { |
1959 |
|
try { |
1960 |
|
pEngineChannel->SetMidiInstrumentMap(map); |
1961 |
|
} catch (Exception e) { |
1962 |
|
dmsg(2,("\t\t\tCould not apply MIDI instrument map %d to part %d: %s\n", map, part, e.Message().c_str())); |
1963 |
|
goto free_sysex_data; |
1964 |
|
} catch (...) { |
1965 |
|
dmsg(2,("\t\t\tCould not apply MIDI instrument map %d to part %d (unknown exception)\n", map, part)); |
1966 |
|
goto free_sysex_data; |
1967 |
|
} |
1968 |
|
} |
1969 |
|
} |
1970 |
|
dmsg(3,("\t\t\tApplied MIDI instrument map %d to part %d.\n", map, part)); |
1971 |
|
break; |
1972 |
|
} |
1973 |
} |
} |
1974 |
} |
} |
1975 |
else if (addr[0] == 0x40 && (addr[1] & 0xf0) == 0x20) { // Part Parameters (2) |
else if (addr[0] == 0x40 && (addr[1] & 0xf0) == 0x20) { // Part Parameters (2) |
2112 |
} |
} |
2113 |
|
|
2114 |
String Engine::Version() { |
String Engine::Version() { |
2115 |
String s = "$Revision: 1.90 $"; |
String s = "$Revision: 1.94 $"; |
2116 |
return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword |
return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword |
2117 |
} |
} |
2118 |
|
|