0
$\begingroup$

I have an 44100-rate 4 second sample of a legato violin playing at 440 Hz. I would like to modulate this sample so that it starts at 440 Hz, then transforms its frequency continuously and exponentially to 660 Hz, while maintaining the original timbre.

I have tried pitch shifting directly from 440 to 660 and this works fine, but trying to simply cut the sample into extremely short bits and increase the pitch shift for each consecutive bit resulted in a lot of artifacts.

Do you have any suggestions?

Bonus points if it would be easy to implement in python!

$\endgroup$
  • $\begingroup$ Do you want it to stay 4 seconds or is shorter okay? $\endgroup$ – Cedron Dawg Jul 24 '20 at 22:09
  • $\begingroup$ @CedronDawg Ideally last for four seconds, but I could time-stretch using existing technologies and then manipulate if I knew how long the original had to be to arrive at four seconds... $\endgroup$ – lightning Jul 25 '20 at 1:32
  • $\begingroup$ The simplest way I know is to treat your source file as a huge wave table lookup. At 440Hz with 44100 samples per second you have about 10 samples per cycle. Good for the fundamental, but harmonics may suffer a little with linear interpolation, but I would try it first, then maybe go cubic. You shouldn't need to do any kind of sinc. What you need to do is create a function that translates your playback time point to the lookup time point. Do you need help with that part? $\endgroup$ – Cedron Dawg Jul 25 '20 at 1:38
  • $\begingroup$ @CedronDawg Are you suggesting I sample at successively larger frequencies from the array containing the sample? $\endgroup$ – lightning Jul 25 '20 at 21:54
1
$\begingroup$

You're trying to do the time warp dance. If you were copying the samples point by point, your playback time (destination) and your look up time (source) would be the same. If you wanted to speed it up by a factor of two(one octave), your lookup time (source location in the array) would be moving twice as fast as your sample time (location in your output buffer). For variable speed time, you have to figure out where in the lookup table to grab the next value (function range). Where you are going to write it to is the next spot in the buffer, as in uniform time (function domain). When you calculate the location to get your signal value, it may not land on an integer. You could get some rough sound if you just use the nearest one.

So, you got two choices for better quality.

  1. Increase the density of your lookup table

  2. Use some method (called interpolation) to figure out what the value should be

A. Linear interpolation means draw a line between the two nearest samples and use that height whereever your fraction takes you

B. Polynomial interpolation means use the nearby samples to draw a nice smooth curve, and use that height

C. Sinc interpolation means use the sinc function as a weighted average of many nearby points to get the value

Your musician friends will tell you it doesn't sound right. Instruments are complicated and their timbre varies by frequency and the middle name of the nearest bartender.

That's really the precursor to DSP. Trying to fix the sound so it sounds right is a challenge you can have hours of fun pursuing, as others are. There is lots of material if you look for it. I am not really an expert on that at all.

In a synthesizer wavetable the source location just goes round and round and round... how much faster each step is related to the frequency.

Keep a steady tone by not changing the step size.

Linear growth in time. Add the same amount to each step.

Exponential growth in time. Add a multiple of the previous step size.
For instance,

ThisStep = 1.00001 * PreviousStep

SourceLocation += ThisStep

The step size grows exponentially and so does its accumulation.

Speeding up by a factor of $2^{1/12}$ is one semitone.

There's math problem and solution in there somewhere, I'm sure you'll spot it and solve it to get this done. Or maybe two.

$\endgroup$
  • $\begingroup$ Thanks so much! $\endgroup$ – lightning Jul 26 '20 at 23:02
  • $\begingroup$ @lightning Nice to see you had your "aha" moment on this. Feel free to email me (address in my profile) if you come up with something really cool. $\endgroup$ – Cedron Dawg Jul 26 '20 at 23:10
  • $\begingroup$ @lightning Here's something I want you to try. It's way down my todo list so I won't get to it for a while. Record your instrument at the low end of your frequency scale, then at the high end. Then zoom in with audio editor and capture a set of W waveforms from each file, say 10. These will make two wavetables of different sizes. Run your location on the bigger one and calculate the location within the shorter one by using the proportion of sample counts. Then construct your resultant wave as a weighted average of the two tables. For more fun, change instruments on either end. $\endgroup$ – Cedron Dawg Jul 27 '20 at 0:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.