{"id":17,"date":"2003-03-02T21:00:39","date_gmt":"2003-03-03T05:00:39","guid":{"rendered":"http:\/\/www.earlevel.com\/blog\/?p=17"},"modified":"2010-12-13T00:25:50","modified_gmt":"2010-12-13T08:25:50","slug":"the-bilinear-z-transform","status":"publish","type":"post","link":"https:\/\/www.earlevel.com\/main\/2003\/03\/02\/the-bilinear-z-transform\/","title":{"rendered":"The bilinear z transform"},"content":{"rendered":"<p>The bilinear transform is the most popular method of converting analog filter prototypes in the s domain to the z domain so we can implement them as digital filters. The reason we are interested in these s domain filters is that analog filter theory has been around longer than digital filter theory, so we have available to us a number of popular and useful filters in the s domain. The standard biquads used heavily in audio processing are direct implementations from the s domain using the bilinear transform.<\/p>\n<p>The theory of the bilinear transform is well documented in DSP texts and on the web, so rather than spend time going into the theory, we&#8217;ll cut to the chase and show how to do the transform, using a second order lowpass filter as an example.<\/p>\n<p>The s domain transfer function of a second order lowpass filter is<\/p>\n<blockquote><p><img loading=\"lazy\" decoding=\"async\" src=\"\/DigitalAudio\/images\/BiquadSLp.gif\" alt=\"\" width=\"109\" height=\"46\" align=\"middle\" \/><\/p><\/blockquote>\n<p>To move to the z domain, we need to substitute for s in terms of z. At the same time, we &#8220;pre-warp&#8221; the response using the tan function in order to wrap the infinite s plane onto the circular z plane. The combined substitution is<\/p>\n<blockquote><p><img loading=\"lazy\" decoding=\"async\" src=\"\/DigitalAudio\/images\/bilinearSDef.gif\" alt=\"\" width=\"366\" height=\"35\" \/><\/p><\/blockquote>\n<p>Here&#8217;s our z domain transfer function after substituting for s:<\/p>\n<blockquote><p><img loading=\"lazy\" decoding=\"async\" src=\"\/DigitalAudio\/images\/bilinearEx1.gif\" alt=\"\" width=\"200\" height=\"65\" \/><\/p><\/blockquote>\n<p>In order to solve for our filter coefficients, we need to get the equation into the form of a second order polynomial in the numerator (the zeros) and another second order polynomial in the denominator (the poles). That is, we need it to look something like this:<\/p>\n<blockquote><p><img loading=\"lazy\" decoding=\"async\" src=\"\/DigitalAudio\/images\/secondOrderXferFunc.gif\" alt=\"\" width=\"158\" height=\"44\" \/><\/p><\/blockquote>\n<p>It helps to use a math package to cut down on some of the tedious work. If we take the right side of the equation and ask MathCad to &#8220;simplify&#8221;, it gives<\/p>\n<blockquote><p><img loading=\"lazy\" decoding=\"async\" src=\"\/DigitalAudio\/images\/bilinearEx2.gif\" alt=\"\" width=\"412\" height=\"34\" \/><\/p><\/blockquote>\n<p>The first thing we see is that there are too many Q&#8217;s, so divide the top and bottom by Q, resulting in<\/p>\n<blockquote><p><img loading=\"lazy\" decoding=\"async\" src=\"\/DigitalAudio\/images\/bilinearEx3.gif\" alt=\"\" width=\"268\" height=\"50\" \/><\/p><\/blockquote>\n<p>Now combine terms in the numerator and rearrange in descending powers of z; do the same for the denominator:<\/p>\n<blockquote><p><img loading=\"lazy\" decoding=\"async\" src=\"\/DigitalAudio\/images\/bilinearEx4.gif\" alt=\"\" width=\"275\" height=\"51\" \/><\/p><\/blockquote>\n<p>The z operator means delay, and its power tell us how many samples. Positive powers of z are in the future, and negative powers are in the past. Our filter can&#8217;t see into the future (we call such filters &#8220;non-causal&#8221;), so we need to reduce the powers of z to zero and below (to make it causal). To do this we multiply the numerator and denominator by\u00a0<img loading=\"lazy\" decoding=\"async\" src=\"\/DigitalAudio\/images\/z-2.gif\" alt=\"\" width=\"15\" height=\"12\" \/>, which subtracts two from each power of z, and gives us our final form:<\/p>\n<blockquote><p><img loading=\"lazy\" decoding=\"async\" src=\"\/DigitalAudio\/images\/bilinearEx5.gif\" alt=\"\" width=\"339\" height=\"51\" \/><\/p><\/blockquote>\n<p>Our coefficients are now evident:<\/p>\n<blockquote><p><img loading=\"lazy\" decoding=\"async\" src=\"\/DigitalAudio\/images\/bilinearEx6.gif\" alt=\"\" width=\"353\" height=\"58\" \/><\/p><\/blockquote>\n<p>Because the b0 coefficient is associated with y[n], the filter output, we divide everything by b0 to normalize the filter. Here we also note some convenient relationships between the &#8220;a&#8221; coefficients:<\/p>\n<blockquote><p><img loading=\"lazy\" decoding=\"async\" src=\"\/DigitalAudio\/images\/bilinearEx7.gif\" alt=\"\" width=\"371\" height=\"106\" \/><\/p><\/blockquote>\n<p>As a further efficiency, you can compute the common numerator term once and use it where needed. When calculating the coefficients, Q is the filter Q value (for a Butterworth lowpass, where the passband is flat with no corner peaking, use 0.7071, which is the reciprocal of the square root of two). Recall that we defined K as<\/p>\n<blockquote><p><img loading=\"lazy\" decoding=\"async\" src=\"\/DigitalAudio\/images\/biquadKdef.gif\" alt=\"\" width=\"80\" height=\"30\" \/><\/p><\/blockquote>\n<p>where Fc is the filter corner frequency you want, and Fs is the sample rate.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The bilinear transform is the most popular method of converting analog filter prototypes in the s domain to the z domain so we can implement them as digital filters. The reason we are interested in these s domain filters is &hellip; <a href=\"https:\/\/www.earlevel.com\/main\/2003\/03\/02\/the-bilinear-z-transform\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4,8,9],"tags":[],"_links":{"self":[{"href":"https:\/\/www.earlevel.com\/main\/wp-json\/wp\/v2\/posts\/17"}],"collection":[{"href":"https:\/\/www.earlevel.com\/main\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.earlevel.com\/main\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.earlevel.com\/main\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.earlevel.com\/main\/wp-json\/wp\/v2\/comments?post=17"}],"version-history":[{"count":0,"href":"https:\/\/www.earlevel.com\/main\/wp-json\/wp\/v2\/posts\/17\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.earlevel.com\/main\/wp-json\/wp\/v2\/media?parent=17"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.earlevel.com\/main\/wp-json\/wp\/v2\/categories?post=17"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.earlevel.com\/main\/wp-json\/wp\/v2\/tags?post=17"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}