{"id":113,"date":"2019-10-01T16:46:25","date_gmt":"2019-10-01T16:46:25","guid":{"rendered":"https:\/\/synthnotes.ucsd.edu\/wp7\/?p=113"},"modified":"2020-09-17T22:43:46","modified_gmt":"2020-09-17T22:43:46","slug":"interpolation","status":"publish","type":"post","link":"https:\/\/synthnotes.ucsd.edu\/wp7\/index.php\/2019\/10\/01\/interpolation\/","title":{"rendered":"Interpolation"},"content":{"rendered":"<h2>Interpolation<\/h2>\n<p>When we use phase truncation on a phasor whose frequency is low relative the tablesize and sampling rate, consecutive samples may not change. To counter this, we can use different methods of interpolation to more accurately represent the waveforms when the periods of the phasor are very small compared to the size of the table.<\/p>\n<p>It is essentially the ratio between the period of the phasor and size of the table&#8230;<\/p>\n<h3>Linear Interpolation<\/h3>\n<p>Linear interpolation involves using the fractional part of the calculated phase to calculate the &#8220;distance&#8221; between the two points on which we lie. If, for instance, our calculated index is 32.76, we would need to look at <em>both<\/em>&nbsp;indexes 32 and 33. We would then take their respective values, `t[32]` and `t[33]`, calculate the difference between the latter index and the earlier, multiply by the fractional part, then add it to the index as we would in phase truncation:<\/p>\n<pre>&nbsp;\/\/ calculate the fractional part\nfrac = index - int(index);\n\n\/\/ get the difference and wrap the index (can also use a modulo)\nwhile(index &gt; tablesize)\n    index = index - tablesize;\n\nif (index == tablesize-1) \n    diff = t[0] - t[index]; \/\/ wrap\nelse\n    diff = t[index+1] - t[index]; \/\/ no need to wrap\n\n\/\/ get the interpolated output\nout = t[index] + (diff * frac);<\/pre>\n<p>where `t` is the table filled with the sine wave and `index` is the calculated index with a phasor multiplied by the size of the table minus 1.<\/p>\n<h3>Hermite (Cubic) Interpolation<\/h3>\n<p>A more accurate interpolation technique is the Hermite or cubic method. What this method essentially does is to find the coefficients <em>a<\/em>, <em>b<\/em>, <em>c<\/em>, and <em>d<\/em>&nbsp;for the third degree polynomial <em>f(x)<\/em> and its derivative, <em>f'(x)<\/em>, at <em>x = 0<\/em> and <em>x = 1<\/em>.<\/p>\n<span class=\"wp-katex-eq\" data-display=\"false\">\\begin{aligned}&amp; f(x) = ax^3 + bx^2 + cx + d \\\\ &amp; f&#039;(x) = 3ax^2 + 2bx + c \\end{aligned} <\/span>\n<h4>Calculating the Coefficients<\/h4>\n<p>Given four points, (<em>x0<\/em>, <em>y0<\/em>), (<em>x1<\/em>, <em>y1<\/em>), (<em>x2<\/em>, <em>y2<\/em>), (<em>x3<\/em>, <em>y3<\/em>), we can calculate the coefficients with the following:<\/p>\n<p><span class=\"wp-katex-eq\" data-display=\"false\"> \\begin{aligned} &amp; a = -\\frac{y_{0}}{2} + \\frac{3y_{1}}{2} - \\frac{3y_{2}}{2} + \\frac{y_{3}}{2} \\\\ &amp; b = y_{0} - \\frac{5y_{1}}{2} + 2y_{2} - \\frac{y_{3}}{2} \\\\ &amp; c = -\\frac{y_{0}}{2} + \\frac{y_{2}}{2} \\\\ &amp; d = y_{1} \\end{aligned} <\/span><br>This is called the Catmull-Rom spline.<\/p>\n<p>Calculating these coefficients and plugging them into the third degree polynomial (the first equation) gives us the cubic interpolative values between <em>x = 0<\/em>&nbsp;and <em>x = 1<\/em>.<\/p>\n<h4>Putting it Together<\/h4>\n<p>Given an index <em>i<\/em>, we need to get the indices <em>i-1<\/em>, <em>i<\/em>, <em>i+1<\/em>, and <em>i+2<\/em> to use them in our cubic interpolator.<\/p>\n<pre>float cubicInterpolator(float idx, float *table)\n{\n    long trunc = (long) idx; \/\/ truncate the index but don't overwrite\n    float frac = idx - trunc; \/\/ get the fractional part\n\n    \/\/ get the indices\n    int x0 = wrap(trunc-1, tableSize-1);\n    int x1 = wrap(trunc, tableSize-1);\n    int x2 = wrap(trunc+1, tableSize-1);\n    int x3 = wrap(trunc+2, tableSize-1);\n\n    \/\/ calculate the coefficients\n    float a = -0.5*table[x0] + 1.5*table[x1] - 1.5*table[x2] + 0.5*table[x3];\n    float b = table[x0] - 2.5*table[x1] + 2.0*table[x2] - 0.5*table[x3];\n    float c = -0.5*table[x0] + 0.5*table[x2];\n    float d = table[x1];\n\n    return (a*(frac*frac*frac) + b*(frac*frac) + c*frac + d);\n}<\/pre>\n<h4>Phase Truncation, Linear Interpolation, and Cubic Interpolation Compared<\/h4>\n<p>If we push this to an extreme to show the differences, this plot shows samples 32 to 64 of the same 100Hz sine wave lookup sampled at 8kHz using either phase truncation (purple), linear interpolation (green), or cubic interpolation (blue) from a tablesize of 16:<\/p>\n<p><a href=\"https:\/\/synthnotes.ucsd.edu\/wp7\/wp-content\/uploads\/2019\/10\/interpComparison.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-167\" src=\"https:\/\/synthnotes.ucsd.edu\/wp7\/wp-content\/uploads\/2019\/10\/interpComparison.png\" alt=\"\" width=\"1540\" height=\"572\" srcset=\"https:\/\/synthnotes.ucsd.edu\/wp7\/wp-content\/uploads\/2019\/10\/interpComparison.png 1540w, https:\/\/synthnotes.ucsd.edu\/wp7\/wp-content\/uploads\/2019\/10\/interpComparison-300x111.png 300w, https:\/\/synthnotes.ucsd.edu\/wp7\/wp-content\/uploads\/2019\/10\/interpComparison-768x285.png 768w, https:\/\/synthnotes.ucsd.edu\/wp7\/wp-content\/uploads\/2019\/10\/interpComparison-1024x380.png 1024w, https:\/\/synthnotes.ucsd.edu\/wp7\/wp-content\/uploads\/2019\/10\/interpComparison-624x232.png 624w\" sizes=\"auto, (max-width: 1540px) 100vw, 1540px\" \/><\/a><\/p>\n<h4>Listen<\/h4>\n<p>Listen to each of the different interpolation methods below. Be particularly aware of the differences at extremely high and low frequencies.<\/p>\n\n\n<figure class=\"wp-block-audio\"><audio controls src=\"https:\/\/synthnotes.ucsd.edu\/wp7\/wp-content\/uploads\/2020\/09\/trunc.wav\"><\/audio><figcaption>sine sweep with phase truncation<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-audio\"><audio controls src=\"https:\/\/synthnotes.ucsd.edu\/wp7\/wp-content\/uploads\/2020\/09\/2phi.wav\"><\/audio><figcaption>sine sweep with 2 point linear interpolation<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-audio\"><audio controls src=\"https:\/\/synthnotes.ucsd.edu\/wp7\/wp-content\/uploads\/2020\/09\/4phi.wav\"><\/audio><figcaption>sine sweep with 4 point cubic interpolation<\/figcaption><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>Interpolation When we use phase truncation on a phasor whose frequency is low relative the tablesize and sampling rate, consecutive samples may not change. To counter this, we can use different methods of interpolation to more accurately represent the waveforms when the periods of the phasor are very small compared to the size of the [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-113","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/synthnotes.ucsd.edu\/wp7\/index.php\/wp-json\/wp\/v2\/posts\/113","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/synthnotes.ucsd.edu\/wp7\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/synthnotes.ucsd.edu\/wp7\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/synthnotes.ucsd.edu\/wp7\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/synthnotes.ucsd.edu\/wp7\/index.php\/wp-json\/wp\/v2\/comments?post=113"}],"version-history":[{"count":15,"href":"https:\/\/synthnotes.ucsd.edu\/wp7\/index.php\/wp-json\/wp\/v2\/posts\/113\/revisions"}],"predecessor-version":[{"id":585,"href":"https:\/\/synthnotes.ucsd.edu\/wp7\/index.php\/wp-json\/wp\/v2\/posts\/113\/revisions\/585"}],"wp:attachment":[{"href":"https:\/\/synthnotes.ucsd.edu\/wp7\/index.php\/wp-json\/wp\/v2\/media?parent=113"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/synthnotes.ucsd.edu\/wp7\/index.php\/wp-json\/wp\/v2\/categories?post=113"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/synthnotes.ucsd.edu\/wp7\/index.php\/wp-json\/wp\/v2\/tags?post=113"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}