Designing a Heartbeat That Changes Speed Gradually Based on a Parameter.


#1

I am attempting to design a looping heartbeat that will change speed gradually based on a parameter. A previous sound designer had implemented a heartbeat, but the implementation has a couple of problems that I want to improve upon:

  1. For each loop, there is only a single “lub” sound. It should make 2 successive sounds to produce a “lub dub” like a real heartbeat (and thereby emulate the atrioventricular valves and semilunar valves, as Wikipedia has informed me).

  2. The current implementation has numerous loop regions of different length that are selected by the speed parameter. This causes the heartbeat to increase in speed step-wise, not gradually.

I’d like to make the heartbeat increase in speed gradually, and I’d also like to make the amount of time between the “lub” and the “dub” speed up proportionally with the overall heart rate.

I have separate samples for the “lub” and “dub”. I am just struggling to conceive of a graceful way to implement this in FMOD. I have setup an event with the two sounds in a loop region, and at this static speed it sounds good. Adjusting the master pitch gets the speed change I want, but I don’t want to change the pitch of the samples. It seems like there must be a way to just make them trigger faster or slower based on the speed parameter. I keep thinking tempo automation has to be the way, but I can’t conceive of a way to do that either.

I’m thinking I’m going to have to script the behavior I want in the game engine, but I thought I should field the question here to see if anyone had a good suggestion for how to gracefully implement this effect.

Do you have a good implementation idea for me?

[Using FMOD Studio with Unity]


#2

Of course–since I just posted about it–I finally had a breakthrough.

I setup two Scatter Instruments on the Speed parameter instead of the timeline. I set the scatter distance to 0 and the spawn interval to 600 ms, with the spawn rate automated from 50% to 160% based on the speed parameter.

I offset the “dub” by setting the delay interval to 320 ms. As long as the playback starts with the speed at 0, the timing between the “lub” and the “dub” sounds perfect and scales properly as the speed increases.

I feel like this could be improved upon though. I wish that the “dub” was explicitly set to follow the “lub”, so that I could prevent potential synchronization issues. Also, if the sound explicitly follows the other, I could give them little timing randomizations to help make it sound more organic. And if I have a technique for that, I could also use it to integrate a squishy sound to follow each heartbeat.

I’d appreciate any suggestions you might have.


#3

The method your predecessor used, of having multiple loop regions, is the method we generally recommend. It’s relatively easy to set up and maintain, and the “stepped” nature of the changes to the interval is rarely noticeable. (If you want to have both a “lub” and a “dub” and for the time between them to vary with the speed of the heart beat, you can do it by using two separate arrays of transition markers instead of a single array of loop regions.)

That said, if you do want to use a scatterer instrument, here’s how to get the behavior you want:

  1. Remove all the single instruments from your scatterer instrument’s playlist, and then add to said playlist one event instrument.
  2. Double-click on this instrument to open the nested event.
  3. Add the speed parameter to the nested event.
  4. Add a scatterer instrument to the timeline of the nested event. Set the new scatterer instrument’s Min & Max scatter distance to 0 and automate its spawn rate on the speed parameter.
  5. Add your “lub” and “dub” files to the new scatterer instrument’s playlist in the order you’d like them to play in.
  6. Set the scatterer instrument’s spawn total to 2, and set its playlist mode to sequential. (Which is to say, there’s a button at the top of the playlist with a picture of a die on it; click that button until it stops being yellow.) This ensures that the playlist will always play both of its entries in the order in which they are presented when the scatterer instrument is triggered.

The result of following the above steps is that when the scatterer instrument in the parent event is triggered, it will begin playing a heartbeat. The interval of double-beats will be based on the spawn rate automation in the parent event, and the interval between the “lub” and “dub” of each double-beat will be based on the automation in the nested event.


#4

What I did there, was just that - single loop on a timeline, automate the master pitch of the event to speed up the timeline. Place the “lub” and the “dub” one after another on the timeline.

However, in addition to that, also automate the pitches of the “lub” and “dub” triggers themselves with an opposite pitch envelope. This way you can retain a sequence, get a step-free change in beat/rate while retaining pitch. And the Lubs and the Dubs can have their own random variations each.

This lets you even do more complicated sequences, like a rate-variable “ba dunk ba dunk” of railway train cars for example.

Turned out to be the simplest solution for me. It can also be placed into a nested event for added convenience.


#5

Couldy yet another alternative be a Scatterer with a sequential playlist of the following:

  1. Nested “Lub” (containing a multi-sound with random variations)
  2. Nested “Dub” (likewise)
  3. blank
  4. blank

… and just automating the Spawn Rate?


#6

This could definitely work. You would need to adjust the precise number and order of empty single instruments in the playlist, to match your project’s needs, of course, but it would definitely work.


#7

Ooooo. I really like this approach.

I’ve found that, to me, the heartbeat sounds natural as a triplet pattern (Lub - Dub- Rest). I think that is more or less what I went with in my implementation. However, imagining it right now, I think the lub-dub-rest-rest might sound better for slower heart rates.

I actually think my own heartbeat is more of a triplet.


#8

I think I understand what you’re describing here, but I have a couple concerns about how that would be handled behind-the-scenes. I think what your describing would not be lossy to the audio-- you’re describing straight up pitch changes, not any time-stretching. But I would worry that this is more processor intensive.

If I understand correctly, when you have a fast heart rate, the FMOD engine would have to pitch down the sample, then pitch it up to the global pitch of the timeline. In my head, this would require a lot more math than scripts like a scatterer instrument triggering events based on some timing logic.

I think even though my implementation was a little more convoluted in its setup, it probably is more performant. Though I’d love to know more about how the engine handles stuff like this.

Edit: The implementation I ended up using was as Joseph Harvey described in his response, using nested scatterer instruments.


#9

Yep, in hindsight I also started thinking maybe a triplet would sound more natural than a 4:4 for heartbeat. That’s easy to customize.

And indeed you are right, resampling up and then back down sounds like something that FMOD Studio may end up doing here. This “pitch up timeline to speed up rate, pitch down multi-sounds to compensate” is a hack, just to get a steplessly adjustable rate AND a freely editable sequence onto a timeline, with random variations. I would also be curious to know what happens ‘under the hood’ (in terms of resampling) when you do it this way.

In this light, maybe some kind of a “step sequencer” module could be useful for Studio, for uses like these. Sequential, timed triggerings that may still need random variations for each trigger.

Another use case example would be the ‘ta-tank tu-tunk ( … delay … )’ rhythm you get when a train car travels along a railyway. You’d need to make the rate of that variable, as well, to match the speed of the train.


#10

Side note: using wavs with lower sample rates makes for shorter buffer reads, so you can slightly optimize performance that way for sounds that get pitched up and down a lot. In case of the heart beat, if it’s just bass, you could resample those assets all the way down to 22050.