--- linuxsampler/trunk/src/engines/gig/Engine.cpp 2008/04/10 17:41:32 1722 +++ linuxsampler/trunk/src/engines/gig/Engine.cpp 2008/07/10 15:00:38 1750 @@ -358,14 +358,13 @@ this->MaxSamplesPerCycle = pAudioOutputDevice->MaxSamplesPerCycle(); this->SampleRate = pAudioOutputDevice->SampleRate(); - // FIXME: audio drivers with varying fragment sizes might be a problem here - MaxFadeOutPos = MaxSamplesPerCycle - int(double(SampleRate) * CONFIG_EG_MIN_RELEASE_TIME) - 1; - if (MaxFadeOutPos < 0) { + MinFadeOutSamples = int(double(SampleRate) * CONFIG_EG_MIN_RELEASE_TIME) - 1; + if (MaxSamplesPerCycle < MinFadeOutSamples) { std::cerr << "gig::Engine: WARNING, CONFIG_EG_MIN_RELEASE_TIME " << "too big for current audio fragment size & sampling rate! " << "May lead to click sounds if voice stealing chimes in!\n" << std::flush; // force volume ramp downs at the beginning of each fragment - MaxFadeOutPos = 0; + MinFadeOutSamples = MaxSamplesPerCycle; // lower minimum release time const float minReleaseTime = (float) MaxSamplesPerCycle / (float) SampleRate; for (RTList::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) { @@ -1728,6 +1727,7 @@ //TODO: not sample accurate yet pEngineChannel->GlobalPanLeft = PanCurve[128 - itControlChangeEvent->Param.CC.Value]; pEngineChannel->GlobalPanRight = PanCurve[itControlChangeEvent->Param.CC.Value]; + pEngineChannel->iLastPanRequest = itControlChangeEvent->Param.CC.Value; break; } case 64: { // sustain @@ -1890,6 +1890,26 @@ if (exclusive_status != 0xF0) goto free_sysex_data; switch (id) { + case 0x7f: { // (Realtime) Universal Sysex (GM Standard) + uint8_t sysex_channel, sub_id1, sub_id2, val_msb, val_lsb;; + if (!reader.pop(&sysex_channel)) goto free_sysex_data; + if (!reader.pop(&sub_id1)) goto free_sysex_data; + if (!reader.pop(&sub_id2)) goto free_sysex_data; + if (!reader.pop(&val_lsb)) goto free_sysex_data; + if (!reader.pop(&val_msb)) goto free_sysex_data; + //TODO: for now we simply ignore the sysex channel, seldom used anyway + switch (sub_id1) { + case 0x04: // Device Control + switch (sub_id2) { + case 0x01: // Master Volume + GLOBAL_VOLUME = + double((uint(val_msb)<<7) | uint(val_lsb)) / 16383.0; + break; + } + break; + } + break; + } case 0x41: { // Roland dmsg(3,("Roland Sysex\n")); uint8_t device_id, model_id, cmd_id; @@ -1926,6 +1946,30 @@ dmsg(3,("\t\t\tNew scale applied.\n")); break; } + case 0x15: { // chromatic / drumkit mode + dmsg(3,("\t\tMIDI Instrument Map Switch\n")); + uint8_t part = addr[1] & 0x0f; + uint8_t map; + if (!reader.pop(&map)) goto free_sysex_data; + for (int i = 0; i < engineChannels.size(); ++i) { + EngineChannel* pEngineChannel = engineChannels[i]; + if (pEngineChannel->midiChannel == part || + pEngineChannel->midiChannel == midi_chan_all + ) { + try { + pEngineChannel->SetMidiInstrumentMap(map); + } catch (Exception e) { + dmsg(2,("\t\t\tCould not apply MIDI instrument map %d to part %d: %s\n", map, part, e.Message().c_str())); + goto free_sysex_data; + } catch (...) { + dmsg(2,("\t\t\tCould not apply MIDI instrument map %d to part %d (unknown exception)\n", map, part)); + goto free_sysex_data; + } + } + } + dmsg(3,("\t\t\tApplied MIDI instrument map %d to part %d.\n", map, part)); + break; + } } } else if (addr[0] == 0x40 && (addr[1] & 0xf0) == 0x20) { // Part Parameters (2) @@ -2068,7 +2112,7 @@ } String Engine::Version() { - String s = "$Revision: 1.90 $"; + String s = "$Revision: 1.94 $"; return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword }