tloimu / adapt-ffb-joy

adapt-ffb-joy
https://github.com/tloimu/adapt-ffb-joy/wiki
197 stars 65 forks source link

Periodic effects don't work with all frequencies ("feature" of the joystick) #6

Closed GoogleCodeExporter closed 1 year ago

GoogleCodeExporter commented 9 years ago
saldsj3 reports, that:

"For Sine, and Square waves, 46-50 doesn't work. For triangle waves, 46-50 do 
work. For all periodic effects, wavelength 84-100 don't work.

I also had issues with magnitude, it seems certain attack levels / fade times 
are necessary to get the joystick to react to a lower magnitude value,  A fade 
time of 0 seemed to always result in a full force effect."

The non-functioning frequencies are because of the joystick itself. The adapter 
needs a new feature that converts the non-functioning frequencies to some 
useful frequency value for the joystick in order to avoid completely missing 
effects.

Original issue reported on code.google.com by tlo...@gmail.com on 24 Jul 2012 at 6:47

ej113 commented 1 year ago

This (1st para) is due to undersampling, not a limitation of the joystick. The default Sample Rate being sent to the joystick for periodic effects is 100Hz. Effects are synthesized by sampling the waveform at the sample rate. This means that when the periodic frequency is 100Hz all of the samples have the same value and there is no oscillation. At 50Hz a sine wave is crossing zero twice per cycle and these are the points that are sampled, so there is also no oscillation. Above 50Hz aliasing will occur.

Sample Rate is set in bytes 15 & 16. 0x64 0x00 corresponds to 100 in units of Hz. This parameter can also be modified on-the-fly using modify code 0x50 and takes immediate effect while the effect is playing. Setting it to a low value for a low frequency periodic (e.g. 10Hz sampling of 1Hz sine wave) makes the effect feel rougher. It is a parameter supported by DirectInput and USB PID.

I set the Sample Rate to the maximum value (0x7F 0x7F => 16383) and tried to find the maximum frequency for periodics. I don't know what the actual saturation value of Sample Rate is or have a way to find out. The highest frequency input value that I got a response for was 169, which I measured at 164Hz. This means the saturation value of Sample Rate must be at least double this, so>330HZ.

I also did a frequency sweep using a phone app "Spectroid" and manually recording the frequency of the peak. Plot below. It looks like a staircase with increasingly large steps - I guess there is probably a hardware explanation for why it was implemented in this way. I started at 45Hz as this was the lowest frequency spike that I could read over background noise. The series isn't complete because it was a fairly unpleasant noise and I was worried about burning out the motors by continuously playing it at maximum gain!

image

There may be a reason why MS drivers always sent a sample rate of 100Hz to the joystick. It is certainly sufficient for smooth rendering of low frequency effects, and doesn't cause much attenuation up to about 25Hz. Perhaps higher sample rates use more processor resources and this causes problems when multiple effects are playing. It is also possible that playing higher frequencies up to the hardware capability of the joystick could reduce it's life, and frequency was being deliberately limited.

Recommendation: Note the default sample period transmitted over USB PID messages is 0 i.e. default for the joystick.

If the USB Sample Period is 0:
    If the periodic Frequency is <= 25Hz:
        Set MIDI Sample Rate to 100Hz
    Else if the periodic Frequency is > 25Hz
        Set MIDI Sample Rate to 4 x Frequency
Else set MIDI Sample Rate to 1/USB Sample Period 

It may be a good idea to also limit the maximum frequency the adapter will send to the joystick to (say 75Hz?) in order to reduce the risk of damage to the hardware.

ej113 commented 1 year ago

I have a theory for the big steps in frequency. I think the FFP must internally be converting frequency back to period with a resolution of 2ms before synthesizing the waveform. There are jumps from (approximately) 100Hz to 125Hz to 167Hz which correspond to periods of 10ms, 8ms and 6ms respectively. Seems a bit of a dozy design decision to transmit integer frequency in Hz and lose low frequency resolution, then convert it to period and lose high frequency resolution...