Skip to content

Stereostim waveform generation. #8

Description

@diglet48

I saw your new stereostim feature on reddit and wanted to add some insight on waveform generation to get you up to speed on the progress made the last few years.

I spent lots of time with Restim to optimize waveform generation. The current algorithm was inspired by phx / aquarium parrot, a small creator on milovana. It generates waveforms based on 4 parameters: the carrier frequency and pulse frequency (both in hz), pulse width and rise time (both in cycles of carrier frequency). This algorithm is also implemented in the FOC-Stim and has been colloquially known as Restim wavelets.

The basic idea is to have relatively short pulses with a rest period in between, so the duty cycle of the waveform is less than 100% to improve power efficiency.

  • Carrier frequency: Historically with three-phase, changing the carrier frequency resulted in unpredictable changes in intensity, so generally a single carrier frequency would be selected for the entire session. This is less of a problem with dual-channel and the FOC-Stim, but the effect of carrier frequency on sensation is still poorly understood and/or minor. I play with fairly high carrier frequency (1700hz) for safety reasons, but most users seem to be OK using frequencies down to approximately 500hz. (the risk with 'low' frequencies is due to electrochemical effects). The equivalent frequency of the coyote is about 5000hz (~100µs pulse width), However, higher frequencies require higher peak power output, my stereostim box cannot deliver sufficient power for frequencies above 1000hz. In practice this means 500-1000hz is often used.
  • Pulse frequency: This parameter has a large impact on whether the sensation feels like a vibrator, or feels smooth. General range 1-100hz. The subjective frequency actually depends on the length of the downtime between pulses, rather than the pulse rate. I'm not too familiar with the coyote, but perhaps you can experiment with this on the coyote?
  • Pulse width: To ensure somewhat symmetric biphasic pulses, the pulse has to be at least a certain number of cycles wide. So the pulse width is specified in number of carrier cycles (3-20 in restim, but vales over 10 are rarely used). It is the number of times the 'pulse' is repeated within a wavelet.
  • Rise time: Smooths out the edges of the pulse. The minimum in Restim is 2 cycles except when the pulse width is 3, then it's 1.5.

To generate these wavelets, I generate a few cycles at the carrier frequency and multiply that by the pulse envelope to smooth out the sharp edges at the start and end of the pulse (the envelope is defined by pulse width and rise time). Each wavelet has a random starting angle of the carrier frequency. These wavelets are generated at a frequency equal to the pulse frequency (up to a maximum of 100% duty cycle).

Pulse frequency really does most of the heavy lifting. The carrier frequency is less important. The pulse width and rise time are not that interesting. Changing pulse width only seems to change the sensation with very specific moving threephase signals, I doubt you can get any effect with dual-channel. Changing the rise time seems to do nothing. To simplify the user interface, you might hide pulse width / rise time behind a menu. I usually use the values 7 and 3 for width/rise. This means the pulse is 7 carrier cycles long, and the pulse envelope ramps up in 3 cycles, 1 cycle at 100% power, and 3 cycles ramp down. The exact envelope shape does not appear to be critical, but my ramp shape is sin(0) to sin(pi/2).

The combination of high carrier frequency and low pulse width results in the highest power efficiency (joules per unit of nerve activation). High carrier frequency, high duty cycle waveforms should be avoided to prevent thermal burns, above 1000hz is approximately where you run into thermal issues with 100% duty cycle signals. Low carrier frequency, high pulse frequency waveforms should be avoided because having pulse frequency anywhere near to the carrier frequency (pulse width less than ~3 carrier cycles) makes absolutely no sense.

For these reasons I recommend to copy this specification where pulse width is specified in carrier cycles and the pulse frequency is limited to around 100hz, it is quite simple and makes it impossible to specify these waveforms you shouldn't use.


Some users have expressed interest in non-sine signals. Certain three-phase signals rely on phase control, which only works when the signal is a single frequency so square waveforms are not possible. For this reason Restim does not support square waves. It is possible to use non-sine waves with dual-channel though.

But there are a couple things you should be aware of. If multiple channels are placed close together (and/or crossing) and the phase is not controlled, you can get unpredictable effects due to interference between the channels. The coyote avoids this by separating the pulses in time, but this requires the pulses to be extremely narrow.

The alternative is to use the same phase-locked carrier on all channels. You may get some interference, but a lot less than if you would use 1000hz carrier on A and 999hz carrier on B.

In lab tests on single nerves, the waveform shape (sine/square/triangle) seems to be completely irrelevant if the pulse width is similar. It is my impression that the debate about sine vs square waves really isn't about the waveform shape, but is all about the pulse width (500hz sine = 1ms, coyote = 100µs) and to a lesser extent, the polarity of the leading pulse and how much time there is between the positive and negative part of the pulse.

The coyote uses square waves with constant amplitude, using the pulse width to control the subjective intensity. Why did the designers do this? I think the answer is very simple: it results in the simplest/cheapest possible output stage. I definitely wouldn't use this as an example of what to do (unless you want to design the cheapest possible output stage ;) ).


There are a few devices on the market such as the 312 and 2B that don't do direct audio passthrough. You cannot really optimize the waveforms for these devices without compromising on stereostim functionality, especially when you get into the wavelet generation stuff.

Good luck.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions