Add Waveform Options to Isochronic Modulator Plug-in

[
Hi.
I’ve found very interest The “Pulse Width” and “fade” control, I’ve tried add to this plugin the waveform option but really it leaves my hands, I don’t have the knowledge to complete the code.

this is what I managed to modify:

;nyquist plug-in
;version 1
;type process
;categories "http://lv2plug.in/ns/lv2core#ModulatorPlugin"
;name "IsoMod2..."
;action "Modulating..."
;info "Isochronic Modulator by Steve Daulton. GPL v.2nhttp://easyspacepro.comnn'Pulse Width' controls the length of each pulse.n'Fade Time' adjusts the fade in/out speed of the pulses.nThe modulation speed/depth transforms gradually fromnthe initial settings to the final settings.nnPlug-in provided as an audio processing effect.nThe author does not endorse or claim any relevancento the theory or practice of brainwave entertainment."

;control wave "Tremolo Shape" choice "sine,triangle,sawtooth,inverse sawtooth,square" 0
;control pw "Pulse Width [50%=Square]" real "%" 40 0 100
;control ft "Fade Time" real "%" 15 0 100
;control startf "Initial Modulation Frequency" real "Hz" 7 1 40
;control endf "Final Modulation Frequency" real "Hz" 2 1 40
;control starta "Initial Modulation Depth" int "%" 100 0 100
;control enda "Final Modulation Depth" int "%" 100 0 100

(setq pw (/ pw 100.0))
(setq  ft (/ ft 400.0))
(setq ft (* ft (min pw (- 1 pw)) 2))

; set tremolo *waveform* 
(setq *waveform* (cond
   ((= wave 0) ; sine
   *sine-table*)
   ((= wave 1) ; triangle
   *tri-table*)
   ((= wave 2) ; sawtooth
   (abs-env (list (pwl 0 -1 .995  1 1 -1 1) (hz-to-step 1.0) t)))
   ((= wave 3) ; inverse sawtooth
   (abs-env (list (pwl 0 1 .995  -1 1 1 1) (hz-to-step 1.0) t)))
   (t ; square
   (abs-env (list (pwl ft 1 (- pw ft) 1 (+ pw ft) -1 (- 1 ft) -1 1 0)(hz-to-step 1.0) t)))   ;; doesn't work

;; Function to generate sweep tone
(defun sweep (sf ef)
     (mult 0.5 (sum 1.0 (fmlfo (pwlv sf 1.0 ef) *waveform*))))

(let* ((starta (/ starta 100.0))
   (enda (/ enda 100.0))
   (wet (pwlv starta 1 enda))
   (dry (sum 1 (mult wet -1))))
   (mult s (sum dry (mult wet (sweep startf endf)))))

Help me with sinewave form please.
Attached example for sine wave.
thank you.
]

The “Pulse Width” code will not work with the other waveforms.
The way that it works with the “Square wave” is that the code creates a custom waveform:

(pwl ft 1 (- pw ft) 1 (+ pw ft) -1 (- 1 ft) -1 1 0)

This simply creates a line that goes up, then along a bit, then down, then along a bit and then up again.

The pwl function is described here: http://www.cs.cmu.edu/~rbd/doc/nyquist/part8.html#index376

On the other hand, the sine waveform is created using a predefined wavetable that is built into Nyquist, so the shape of the wave is fixed.
To create a series of sine pulses (as in your example) requires that space is inserted between each cycle of the waveform - I presume that you created the SineIsochronic.flac file by inserting silence manually?

The alternative method would be to create a custom wave shape for “sine pulses”. This could probably be achieved by generating a single cycle sine wave, and adding it to a longer length of silence. The length of the silence would determine the spaces between the pulses. This custom curve would then be used to create a wavetable for the tremolo oscillator (fmlfo).

Your code for having the other waveforms as well as the pulse waveform is very nearly right. You’ve just missed a couple of parentheses off the end of line 33 (I’m forever making errors like that :slight_smile: )

Your line:

   (abs-env (list (pwl ft 1 (- pw ft) 1 (+ pw ft) -1 (- 1 ft) -1 1 0)(hz-to-step 1.0) t)))   ;; doesn't work

should be:

   (abs-env (list (pwl ft 1 (- pw ft) 1 (+ pw ft) -1 (- 1 ft) -1 1 0)(hz-to-step 1.0) t)))))   ;; does work

For working with Nyquist you really need a text editor that has parentheses matching. If you’re on Windows a really good editor (free) is Notepad++

I’ll have a look at sine pulses when I get time, but it’s late now.

If you look at how “pwl” works you may be able to work out how to create sawtooth and inverse sawtooth pulses.

[

Ok, agree, I follow you.


sine-table …ok.

Of course, manually.

Genial.


:wink:

Ok, you are very kind thanks Steve.

]

Here’s some code that will produce a wavetable with a 50% sine pulse.
Note that unlike the other wavetables this one is all in the positive half of the waveform, so you don’t need

(mult 0.5 (sum 1.0 ..... ))

in the “sweep” function.

(setq duration 0.5)

(abs-env
   (progn
   ;; half sine wave
   ;(setq si (abs-env (osc (hz-to-step 1.0) duration *sine-table* 0)))

   ;; full sine wave
   (setq si (mult 0.5 (sum 1 (osc (hz-to-step 2.0) duration *sine-table* 270))))

   ;; add silence
   (setq pulse (sim si (s-rest 1)))

   ;; create wavetable
   (setq *waveform* (list pulse (hz-to-step 1) T))))

; test it
;(osc 69 1 *waveform*)
(mult s (fmlfo (pwlv 20 1.0 10) *waveform*))

[
Your code is accurate. But I could not merge the varibles ft and pw in. My little knowledge not let me do it.
too, I unknown why modulation deep doesn’t work like should be.

This is what I could change:

;nyquist plug-in
;version 1
;type process
;categories "http://lv2plug.in/ns/lv2core#ModulatorPlugin"
;name "IsoMod3..."
;action "Modulating..."
;info "Isochronic Modulator by Steve Daulton. GPL v.2nhttp://easyspacepro.comnn'Pulse Width' controls the length of each pulse.n'Fade Time' adjusts the fade in/out speed of the pulses.nThe modulation speed/depth transforms gradually fromnthe initial settings to the final settings.nnPlug-in provided as an audio processing effect.nThe author does not endorse or claim any relevancento the theory or practice of brainwave entertainment."

;control wave "Tremolo Shape" choice "sine,square" 0
;control pw "Pulse Width [50%=Square]" real "%" 40 0 100
;control ft "Fade Time" real "%" 15 0 100
;control startf "Initial Modulation Frequency" real "Hz" 7 1 40
;control endf "Final Modulation Frequency" real "Hz" 2 1 40
;control starta "Initial Modulation Depth" int "%" 100 0 100
;control enda "Final Modulation Depth" int "%" 100 0 100

(setq pw (/ pw 100.0))
(setq  ft (/ ft 400.0))
(setq ft (* ft (min pw (- 1 pw)) 2))

; set tremolo *waveform* 
(setq *waveform* (cond
   ((= wave 0) ; sine
   (setq duration 0.5)
   (abs-env
   (progn
   ;; half sine wave
   ;(setq si (abs-env (osc (hz-to-step 1.0) duration *sine-table* 0)))

   ;; full sine wave
   (setq si (mult 0.5 (sum 1 (osc (hz-to-step 2.0) duration *sine-table* 270))))

   ;; add silence
   (setq pulse (sim si (s-rest 1)))

   ;; create wavetable
   (setq *waveform* (list pulse (hz-to-step 1) T)))))
   
   ; test it
   ;(osc 69 1 *waveform*)
   (mult s (fmlfo (pwlv 20 1.0 10) *waveform*))   

   (t ; square
   (abs-env (list (pwl ft 1 (- pw ft) 1 (+ pw ft) -1 (- 1 ft) -1 1 0)(hz-to-step 1.0) t)))))

;; Function to generate sweep tone
(defun sweep (sf ef)
     (mult 0.5 (sum 1.0 (fmlfo (pwlv sf 1.0 ef) *waveform*))))

(let* ((starta (/ starta 100.0))
   (enda (/ enda 100.0))
   (wet (pwlv starta 1 enda))
   (dry (sum 1 (mult wet -1))))
   (mult s (sum dry (mult wet (sweep startf endf)))))

Where put this piece for sine?

ft 1 (- pw ft) 1 (+ pw ft) -1 (- 1 ft) -1 1 0

Thank you.
]

[
I could fix Modulation depth. And thinking …doesn’t necessary modify the pulse width, like this be accurate.

;control startf "Initial Modulation Frequency" real "Hz" 7 0.1 40
;control endf "Final Modulation Frequency" real "Hz" 14 0.1 40
;control starta "Initial Modulation Depth" int "%" 100 0 100
;control enda "Final Modulation Depth" int "%" 100 0 100



   (setq duration 0.5)
   
   (abs-env
   (progn
   ;; half sine wave
   ;(setq si (abs-env (osc (hz-to-step 1.0) duration *sine-table* 0)))

   ;; full sine wave
   (setq si (mult 0.5 (sum 1 (osc (hz-to-step 2.0) duration *sine-table* 270))))

   ;; add silence
   (setq pulse (sim si (s-rest 1)))

   ;; create wavetable
   (setq *waveform* (list pulse (hz-to-step 1) T))))
   
   ; test it
   ;(osc 69 1 *waveform*)
   (mult s (fmlfo (pwlv 20 1.0 10) *waveform*))   

;; Function to generate sweep tone
(defun sweep (sf ef)
     (mult 0.5 (sum 1.0 (fmlfo (pwlv sf 1.0 ef) *waveform*))))

(let* ((starta (/ starta 50.0))
   (enda (/ enda 50.0))
   (wet (pwlv starta 1 enda))
   (dry (sum 1 (mult wet -1))))
   (mult s (sum dry (mult wet (sweep startf endf)))))

Sine Isochronic Modulator was done as a separate plug-in.
What rule I should follow to publish it like new plugin?

Thanks.
]

Congratulations GendeDios, you have made it work :slight_smile:
So there is now the question of the modulation depth, which you have noticed is not quite correct.

Would you prefer that I just fix it so that you can use the effect, or would you prefer that I explain how the code functions so that you can make your own modifications?

I had not heard of Isochronic beats, but I assume that the sine wave pulses are the best type of modulation? (you don’t need the other waveform wave shapes?)

Sorry, I don’t understand.

[
I love programming, it is my first experience in the field of sound, I’d want to know how work each instruction code, but I have the head in another place, I have planned in the future to collaborate on a project or create a new project that involves using sound free software, in that time I hope to have ready all my knowledge.

I appreciate if you can fix the code, I’ve task to learn the Nyquist language.

If it’s not very complicated and you can do the other waveform wave shapes, it would be fantastic, experience the brain entrainment with all possible waveforms is very interesting for me.

“What rule I should follow to publish it like new plugin?” I mean if is there a place to register the new plug-ins and if exist rules for do it.

Thanks for everything
]

Sorry about the delay GendeDios, I’ve been a bit short of time, but here’s some bits that can be used as the modulation wave. You may like to have a play with this and see if you can work out what it’s doing and how. I’ll get back to you about how to integrate this into the main effect.

Steve

;control wave "Pulse Type" choice "Sine,Triangle,Square" 0
;control hz "Frequency" real "Hz" 10 0.01 100
;control pw "Pulse Width" real "%" 30 1 100
;control var "Pulse Variation (bias)" real "%" 50 0 100

;limit input variables to sensible range
(defun sanitise (val minv maxv)
  (min (max val minv) maxv))

;; limit max frequency to 1/2 nyquist frequency
(setq pitch (hz-to-step (sanitise hz 0.01 (/ *sound-srate* 4.0))))

;; To prevent aliasing from occurring pulses the pulses must 
;; be a reasonable length 
(setq pw (/ (sanitise pw 1 100) 100.0))

  ;; avoid division by zero errors
(setq var (sanitise (/ var 100.0) 0.01 0.99))

;;; Define wavetables in functions

;'Sine' pulse wave-table
(defun sinewav (width bias)
  (setf pulse (seq
    (osc (hz-to-step (/  (* 2  bias width))) (* bias width) *sine-table* 270)
    (osc (hz-to-step (/  (* 2 (- 1 bias) width))) (* (- 1 bias) width) *sine-table* 90)))
  (setf pulse (sum 0.5 (mult 0.5 pulse)))
  (abs-env(list (sim pulse (s-rest 1))(hz-to-step 1) T)))

(defun triwav (width bias)
  (setq bias (* 2 (- 0.5 bias)))
  (setq width (/ width 2.0))
  (setq bias (* bias width))
  ;make pulse shape
  (setq pulse (pwl (- width bias) 1 (* width 2) 0 1 0))
  ;make wave-table
  (abs-env (list pulse (hz-to-step 1.0) t)))  

(defun sqwav (pw ft)
  ; fade time = half variation (allow for fade-in + fade-out)
  (setq ft (/ ft 2.0))
  ;fade time as proportion of pulse width
  (setq ft (* pw ft))
  ;make pulse shape
  (setq pulse (pwl ft 1 (- pw ft) 1 pw 0 1 0))
  ;make wave-table
  (abs-env (list pulse (hz-to-step 1.0) t)))

; select required wavetable
(setq *waveform*(case wave
  (0 (sinewav pw var))
  (1 (triwav pw var))
  (T (sqwav pw var))))

(osc pitch 20 *waveform*)

I see that pulse variation (bias) only works to triangle wave, but is great for this wave form.

Don’t worry, the issue going genial, I really like. Take all the time you need brother.

Look again :slight_smile: - the “Pulse Variation (bias)” does something to each waveform, but it does different things to different waveforms.
I couldn’t think of a good name for slider control - perhaps you can think of one.

Shows me this message for sine: Nyquist Did not return audio

I already noticed the difference in square wave.

One thing, is generating a tone that only see the waveform on the top of the graphic.

I’m using 1.3.12 beta.

Not sure why that is - I’ll look into that.
What it should do is to “push” the sine wave shape to one side or the other in similar fashion to what happens with the triangle wave.

The “variation” is the “slope” of the rise/fall of the square wave.

yes, that is intentional. In the original “tremolo” effect the modulating waveform was centred about the zero line, so in order to modulate the track audio it was necessary to raise the waveform into positive values and scale it to within the range of 0 to 1.

The modulation is achieved by multiplying the track wave with the modulation (pulse) wave.
If you consider each individual sample in the track wave, it is being multiplied by the value of the corresponding sample in the modulation (pulse) wave.
zero times any number = zero.
one times any number = the number.
To modulate the track audio we want to be multiplying it by a wave that has sample values in the range of 0 to 1.

The original “tremolo” effect started with a modulation wave (waveform) that had samples in the range -1 to +1.
It was therefore necessary to multiply the waveform by 0.5 and add 1 so that the sample values were in the range 0 to 1.
As you have noticed, these new waves are already in the range 0 to 1, so that will simplify our modulation code.

Does that make sense?

You’re a Wizard, I hope to have someday your knowledge :bulb: .

About the name, I don’t know, You’re the Master.

Hi Steve, still going up the project?

Hi GendeDios,
Recently I’ve been busy with other projects, but I’d like to get back to this one at some time as it has such a lot of scope for further development.
I’ve sent you a PM.

Ok, I’ll be waiting for this great contribution yours which is a breakthrough in the field of health. Greetings.

Better late than never :wink:
Here’s the complete “Isochronic Modulator Plugin” with options for different pulse shapes.

A little bit of documentation:

The name of this effect is “IsoMod 2”

Description:

A variable tremolo type plugin that creates low frequency volume pulses. The modulation frequency (speed) and depth transform gradually from the initial settings to the final settings. The default pulse (“Trapezoid”) is a modified square wave. See below for details of pulse shape selection.

The effect is typically applied to a single tone to create isochronic tones. The author supplies the plugin only as a demonstration of audio processing without endorsing or claiming any relevance to the theory or practice of brainwave entrainment.

Controls:

Pulse type: [choice: Trapezoid, Triangle, Sine. Default: Trapezoid]. (see below).
Pulse shape variation: [0 to 100. Default: 50]. (see below).
Pulse width: [1 to 100. Default 30]. The width of the pulse as a percentage of the time between consecutive pulses.
Initial Modulation Frequency: [1 to 20 Hz. Default 7 Hz]. This is the initial “speed” (pulses per second) at which the pulses occur.
Final Modulation Frequency: [1 to 20 Hz. Default 2 Hz]. This is the “speed” at the end of the selection.
Initial Modulation Depth: [0 to 100 %. Default 50 %]. This controls the difference between the high level of the pulse, and the low level between pulse. When set to 100 %, the processed sound is muted to silence between pulses. At 0 % there is no difference between pulse amplitude and the amplitude between pulses.
Final Modulation Depth: [0 to 100 %. Default 50 %]

Pulse shapes:

Pulses may be one of three basic types: Trapezoid, Triangle or Sine. Each of these types has a range of variations (0 to 100). The default variation is set as 50.

Trapezoid: When “Pulse shape variation” is set to zero, the pulse rises almost instantly to the maximum level, then remains at that level for the duration of the pulse before dropping rapidly back to the lower level. As the “variation” setting is increased, the “slope” at the start and end of the pulse becomes more gradual, thus the pulse shape becomes trapezoid. At 100 % the pulse rises over half the pulse width, then falls over the other half, thus produces a triangle pulse (a trapezoid with a top-side length of zero).

Triangle The default “Triangle” pulse rises over half the pulse width, then falls over the other half. At lower variation settings (slider to the left), the triangle is biased to the left, causing the pulse to rise rapidly and fall gradually. At higher variation settings (slider to the right), the triangle is biased to the right, causing the pulse to rise gradually and fall rapidly.


Sine The default “Sine” pulse rises and falls smoothly in a bell-shape. At lower variation settings (slider to the left), the pulse is biased to the left, causing the pulse to rise rapidly and fall gradually. At higher variation settings (slider to the right), the pulse is biased to the right, causing the pulse to rise gradually and fall rapidly.
isomod2.ny (2.8 KB)
If you try this plugin, please post feedback in this topic.


Thank you master. You are awesome. Thousand blessings. Life will smile you endlessly. It’s Great!
Steve, Where can we make you a donation?
What do you know about transform sound to electromagnetism? like this: http://t.co/yj7LRN0Nf1
Regards.

Glad you like it :smiley:
The donation page is here: http://audacityteam.org/donate/

Interesting idea, but I think the term “sound” waves is misleading as they appear to be referring to vibrations in the MHz range (hundreds of times higher frequency than what we normally refer to as “sound”).