Wohlstand / libOPNMIDI

A Software MIDI Synthesizer library with OPN2 (YM2612) emulator
GNU Lesser General Public License v3.0
96 stars 6 forks source link

Polyphonic portamento #40

Closed jpcima closed 6 years ago

jpcima commented 6 years ago

https://github.com/Wohlstand/libADLMIDI/issues/102

:warning: To test. This adds portamento. To work it needs the MIDI controllers: portamento on/off, portamento time

This work needs to update pitch at frequent rate near the audio sample rate. For this, I add in OPNChipBase a way to call into OPNMIDIplay. The call will do work on all notes to update the pitch based on glide rate.

This update work is a performance destroyer if it's done very frequently, so I counted the audio ticks and implemented a rate limit. Please check CPU impact on low power machines. For now I have defined portamento update rate at 1/32th audio rate.

Also, considering update is made from OPNChipBase, doing the same in libADLMIDI will not allow to make it work on hardware chips. For that case, that should be a sort of timer which invoke this update at intervals.

Wohlstand commented 6 years ago

O, nice surprise to a birthday! :smile: Gotta to test it out even it's experimental thing...

Wohlstand commented 6 years ago

default The thing fails to link :-P

EDIT: Okay, it's my dac_test fails: default

I think you need to replace extern declaration with a function pointer which will allow direct using of emulator without of manual declaration of void opn2_audioTickHandler(void *instance, uint32_t rate) function. I'll apply changes by myself and will post into separate branch you can pull...

jpcima commented 6 years ago

:birthday: :gift:

This linker error :thinking: What program is failing with this? opnmidi_midiplay.cpp has the definition. For others, it may need to define the handler as the empty function.

Wohlstand commented 6 years ago

dac_test tool which does using of emulator directly out of libOPNMIDI

jpcima commented 6 years ago

It "works" but I made a screw up though, because the invocation of the update handler must be performed only for the first chip, not all.

Wohlstand commented 6 years ago

Also, yeah, Portamento works! but... seems it's incorrect, yeah

Attaching a demo: portamento.mid.zip

jpcima commented 6 years ago

Gotta check against real synth but it seems really better after fixing! Anyway, remember this is poly portamento, there is remaining work to get mono working..

jpcima commented 6 years ago

Demo for another sort of portamento mode whis has a "fixed" start. Trivial to implement. https://www.youtube.com/watch?v=o9cvMCHgB2s

Wohlstand commented 6 years ago
will not allow to make it work on hardware chips.

Instead of sample rate based ticking, look into the BIOS clock that is used to iterate MIDI while playing on hardware chip: https://github.com/Wohlstand/libADLMIDI/blob/master/utils/midiplay/adlmidiplay.cpp You will see that:

static unsigned long PrevTimer = BIOStimer;
const unsigned long CurTimer = BIOStimer;
const double eat_delay = (CurTimer - PrevTimer) / (double)NewTimerFreq;
PrevTimer = CurTimer;
tick_delay = adl_tickEvents(myDevice, eat_delay, mindelay);
if(adl_atEnd(myDevice) && tick_delay <= 0)
    stop = true;

while hardware playing, the tickEvents() call is requesting manually which causes internal MIDI player to send all raw data to chip are in "mindelay" length.

While hardware chip playing, the ticking is MUCH more often than ticking the emulator. In a case of hardware, it's the spam of const-length event calls.

jpcima commented 6 years ago

Yeah first priority is to backport PCM rate/native rate selection in libADLMIDI, then portamento can be made. Tick handler needs knowledge of the sample interval.