File: pitch_change.htm

package info (click to toggle)
nyquist 3.20%2Bds-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 58,008 kB
  • sloc: ansic: 74,743; lisp: 17,929; java: 10,723; cpp: 6,690; sh: 171; xml: 58; makefile: 40; python: 15
file content (82 lines) | stat: -rw-r--r-- 4,533 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <meta http-equiv="content-type" content="text/html;
      charset=windows-1252">
    <title>Pitch Change by Resampling Tutorial</title>
    <style>body {max-width: 40em}</style>
  </head>
  <body>
    <h1>Pitch Change by Resampling Tutorial</h1>
    <p><b>Roger B. Dannenberg</b></p>
    <p> This tutorial shows how to change the pitch of a sound using
      resampling. In this example, a source sound is resampled to
      effectively play the sound faster and/or slower. This changes the
      perceived pitch. It also makes the sound play faster and/or
      slower, so the original duration is not preserved. </p>
    <p> To control the playback speed, a control function is used. The
      function specifies the pitch shift in steps, so if the function is
      zero, there is no change. If the signal is 1, the signal is
      shifted up one half-step. If the signal is -2, the signal is
      shifted down a whole-step, etc. </p>
    <p> The control signal can of course change over time. The control
      signal time corresponds to time in the resulting sound. Thus, if
      the control signal jumps from 0 to 5 at time 3, the resulting
      sound will jump up a musical fourth (5 half-steps) at time 3. This
      may or may not be time 3 in the source sound. </p>
    <p> The code implements VARIABLE-RESAMPLE which takes two
      parameters: </p>
    <ul>
      <li>steps -- the pitch control function </li>
      <li>snd -- the source sound to be resampled </li>
    </ul>
    The function works as follows: First, steps is converted to ratio,
    which is the speed change expressed as a ratio. E.g. when steps is
    12 (an octave), ratio will be 2 (a 2:1 ratio) Second, ratio is
    integrated to get map. The map is a function from real time to the
    score. Note that the slope of the map at any time determines the
    amount of speedup. Finally, SND-COMPOSE is used to map the source
    sound according to the tempo map. Because SND-COMPOSE is defined to
    output the sample rate of the map, we coerce the sample rate of map
    to *sound-srate*.
    <p> This function could be improved by adding code to handle stereo
      inputs. Also, this function should really be implemented using
      snd-resamplev, which uses a high-quality resampling algorithm.
      Unfortunately, there a bug in snd-resamplev, so until the bug is
      fixed, snd-compose actually sounds better. </p>
    <p> The resulting sound ends whenever either steps or snd come to an
      end. To control duration, you may want to make sure that the
      source sound is much longer than the control function. That way,
      even if you speed it up, it will still last long enough to exhaust
      the control function, and you know by design how long that is. You
      can also apply an envelope to the result to trim it to a known
      length. </p>
    <p> So, here finally is the implementation (first in SAL syntax, and
      then in Lisp syntax in small print): </p>
    <pre>function variable-resample(steps, snd)<br>  begin<br>    with p1 = log(2.0) / 12,    ; p1 helps convert steps to a ratio
         ratio = s-exp(steps * p1) ; pitch ratio
         map = integrate(ratio) ; map from real-time to sound time
    return snd-compose(snd, force-srate(*sound-srate*, map))<br>  end<br>&nbsp;<br><small><small>(defun variable-resample (steps snd)
  (let ((p1 (/ (log 2.0) 12))  ; p1 helps convert steps to a ratio
        ratio map)
    (setf ratio (s-exp (mult steps p1))) ; pitch ratio
    (setf map (integrate ratio)) ; map from real-time to sound time
    (snd-compose snd (force-srate *sound-srate* map))))
</small></small></pre><small><small>
</small></small>Here is an example: the PWL control function is initially zero (no
transposition), but starting at time 1.0, it rises to 2.0 in 0.1s
where it remains until time 3.0. The function ends at time 3.0.
The sound to be modified in this case is a simple sinusoid with a
duration of 8. In this case, the PWL function finishes at 3.0s, well
before the OSC sound comes to an end.<pre>play variable-resample(pwl(1.0, 0.0, 1.1, 2.0, 3.0, 2.0, 3.0), <br>                       osc(c4, 8.0))
</pre>
<pre><small><small>(play (variable-resample (pwl 1.0 0.0 1.1 2.0 3.0 2.0 3.0) (osc c4 8.0)))
</small></small></pre><small><small>
</small></small>Note that you can replace <tt>osc(c4, 8.0)</tt> with any sound, including one
read from a sound file using <tt>s-read</tt>.





</body></html>