tag:blogger.com,1999:blog-72256982772118400792024-03-13T07:39:45.346-07:00bjorgBjorn Rochehttp://www.blogger.com/profile/17072425815152893296noreply@blogger.comBlogger23125tag:blogger.com,1999:blog-7225698277211840079.post-9779447856486152052013-11-20T13:41:00.002-08:002013-11-20T13:47:57.493-08:00Solving acoustics problems<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: justify;"><tbody>
<tr><td style="text-align: center;"><a href="http://3.bp.blogspot.com/-3G3-yfl7B60/Uo0iSBXGaEI/AAAAAAAAAEs/bqVBHHWRIPI/s1600/art_dan2.gif" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" height="251" src="http://3.bp.blogspot.com/-3G3-yfl7B60/Uo0iSBXGaEI/AAAAAAAAAEs/bqVBHHWRIPI/s320/art_dan2.gif" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">A "waterfall plot" like this one is one of many tools used by<br />
acousticians to determine the problems with a room.<br />
Photo from <a href="http://realtraps.com/">realtraps</a> which provides high quality bass traps,<br />
an important type of acoustic treatment.</td></tr>
</tbody></table>
<div style="text-align: justify;">
I recently received the following letter (edited):</div>
<div style="text-align: justify;">
<span style="font-size: x-small;"><i> </i></span></div>
<div style="text-align: justify;">
<span style="font-size: x-small;"><i><br /></i></span></div>
<div style="text-align: justify;">
<span style="font-size: x-small;"><i>Greetings,</i></span></div>
<div style="text-align: justify;">
<span style="font-size: x-small;"><i><br /></i></span></div>
<div style="text-align: justify;">
<span style="font-size: x-small;"><i><span class="Apple-tab-span" style="white-space: pre;"> </span>The echo in my local church is really bad. I am lucky if I can understand 10% of what’s being said. I have checked with other members of the congregation and without exception they all have the same problem. </i></span></div>
<div style="text-align: justify;">
<span style="font-size: x-small;"><i><br /></i></span></div>
<div style="text-align: justify;">
<span style="font-size: x-small;"><i><span class="Apple-tab-span" style="white-space: pre;"> </span>The church is medium size with high vaulted ceiling, very large windows with pillars spaced throughout. The floor is mostly wood. The speakers are flat against the side walls, spaced approx 15 metres apart and approx 10 feet above the floor.</i></span></div>
<div style="text-align: justify;">
<span style="font-size: x-small;"><i><br /></i></span></div>
<div style="text-align: justify;">
<span style="font-size: x-small;"><i><span class="Apple-tab-span" style="white-space: pre;"> </span>The speakers are apparently ‘top of the range’… I just wonder if a graphic equalizer was used between the microphone and speaker, would this ‘clean up’ the sound a little?</i></span></div>
<div style="text-align: justify;">
<span style="font-size: x-small;"><i><br /></i></span></div>
<div style="text-align: justify;">
<span style="font-size: x-small;"><i><span class="Apple-tab-span" style="white-space: pre;"> </span>I know that lining the walls with acoustic tiles and carpeting the floor would lessen the echo, but, we don’t want to do that if we can avoid it.</i></span></div>
<div style="text-align: justify;">
<span style="font-size: x-small;"><i><br /></i></span></div>
<div style="text-align: justify;">
<span style="font-size: x-small;"><i><span class="Apple-tab-span" style="white-space: pre;"> </span>With regard to putting carpet on the floor, my thoughts are that instead of sound being absorbed by the carpet, the congregation present would absorb just as much as the carpet?. One other theory I have is regarding the speakers.</i></span></div>
<div style="text-align: justify;">
<span style="font-size: x-small;"><i><br /></i></span></div>
<div style="text-align: justify;">
<span style="font-size: x-small;"><i><span class="Apple-tab-span" style="white-space: pre;"> </span>If the speakers were moved…</i></span></div>
<div style="text-align: justify;">
<span style="font-size: x-small;"><i><br /></i></span></div>
<div style="text-align: justify;">
<span style="font-size: x-small;"><i>Michael</i></span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Hey Michael,</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
I sympathize with you. Going to service every week and not being able to understand what is being said must be very frustrating. While this is not the kind of thing I do every day, I do have some training in this area and will do my best to give you something helpful.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Most churches are built with little attention to acoustics and old churches were built before there was any understanding of what acoustics is. With all those reflective surfaces and no care taken to prevent the acoustic problems that they create, problems are inevitable, and sometimes, such as in your church, they are simply out of hand. In a situation like that, even a great sound-system won't be able to solve the problem.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
I recommend you hire a professional in your area to come look at the space and be able to give some more specific feedback. To have them improve the situation may cost anywhere from hundreds to tens of thousands of dollars (or even more) depending on the cause of problem. However, it's helpful to have some idea of what some of the solutions are so that when you hire that professional you are prepared for what's to come. You might be able to do some more research and take a stab at solving these issues yourself.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
For example, it might be useful to listen to room and conjecture, even without measurements, if the problem is bound to specific frequencies or if it's just a problem of too many echos. If you are a trained listener you might be able to stand in the room in various places, clap loudly and listen to get a sense of this. Although even a trained listener would never substitute such methods for actual measurements, I often find this method useful for developing a hypothesis (eg. I might listen and say "I believe there is a problem in the low frequencies" before measuring. Then use measurements to confirm or reject this hypothesis). Also, look at the room, are there lots of parallel walls? If so, you are likely suffering from problems at specific frequencies and it's possible that a targeted, and probably less expensive, approach will help.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Another thing you can do is find someone with some stage acting experience and have them speak loud and clear at the pulpit. Have them do this both with and without the sound system and listen to the results. If they sound much clearer without the sound-system than with the sound-system, then that suggests that your sound-system may be causing at least some of the problems.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="white-space: pre;">If you can't afford an acoustician, but you are willing to experiment a bit, this kind of testing might lead you to something. For example, maybe you notice some large open parallel walls and you agree that covering one or both of them with some heavy draperies is either acceptable or would look nice. You could try it and see if it helps. It's no guarantee, but it might make a difference. Draperies are, of course, unlikely to make that much difference by themselves, so you might consider putting acoustic absorbing material behind them.</span></div>
<div style="text-align: justify;">
<span style="white-space: pre;"><br /></span></div>
<div style="text-align: justify;">
<span style="white-space: pre;">Be warned, however, that acoustic treatments done by amateurs without measurements are often beset with problems. For example, you may reduce the overall reverberation time, but leave lots of long echos at certain frequencies. This can be yield results that are no better than where you started -- possibly even worse (although in your case I think that's unlikely).</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Here are the types of things a professional is likely to recommend. You've already alluded to all of them, but I'll repeat them with some more detail. I put them roughly in order of how likely they are to help, but it does depend on your specific situation:</div>
<div style="text-align: justify;">
</div>
<ul>
<li><b>Acoustic treatments.</b> Churches like the one you describe are notorious for highly reflective surfaces like stone and glass, and as you surmised, adding absorptive materials to the walls, floors and ceiling will reduce the echo significantly. Also as you surmised, floor covering may be of limited effectiveness since people do also absorb and diffuse sound, but, of course, it depends on how much of the floor they cover and where. I understand your hesitation to go this route since it may impact the aesthetics of the church, and it may be expensive, but, as I mentioned above, depending on the specific situation, you may be able to achieve a dramatic result in acoustics with relatively little visual impact, and depending on the treatment needed you may be able to keep your costs controlled. You should also be able to collaborate with someone who can create acoustic treatments that are either not noticeable or enhance the esthetics of your space. (Of course, you'll also need someone familiar with things like local fire codes!)</li>
<li><b>Adjusting the speakers.</b> It's certainly possible that putting the speakers in another location would help. If they were hung by a contractor or someone who did not take acoustics into account, they are likely to be placed poorly. Location matters more than the quality of the speakers themselves. Also, if the speakers are not in one cluster at the front, adding the appropriate delay to each set of speaker may help to ensure that sound arrives "coherently" from all speakers, which can improve intelligibility significantly. Devices to provide this kind of delay, and lots of other features, are sold under various names such as "speaker processors," and "speaker array controllers," etc.</li>
<li><b>Electronic tools.</b> Although this is likely to be least effective, you can usually achieve some improvement with EQ, as you suggested. For permanent installations, I prefer parametric EQs, but a high quality graphic will also work. An ad-hoc technique for setting the EQ is to increase the gain until you hear feedback, and then notch out the EQ frequency that causes the feedback. Continue increasing the gain until you are happy with the results. You must be very careful to protect your speakers and your hearing when using this technique, both of which can be easily damaged if you don't know what you are doing. Most speaker processors have built-in parametric EQs and some even come with a calibrated mike that you can use with the device to adjust the settings for you automatically. I've done this, and it works great, especially with a little manual tweaking, but you do have to know what you are doing. But, of course, you can't work miracles in a bad room.</li>
</ul>
Bjorn Rochehttp://www.blogger.com/profile/17072425815152893296noreply@blogger.com0tag:blogger.com,1999:blog-7225698277211840079.post-76700005407901696342013-09-21T08:53:00.000-07:002013-09-21T08:53:21.758-07:00Mapping Parameters<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="http://2.bp.blogspot.com/-6eiXwhp5NGw/Uj26GgtrA_I/AAAAAAAAAEY/LY2W9VlyQg8/s1600/linear+mapping.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" src="http://2.bp.blogspot.com/-6eiXwhp5NGw/Uj26GgtrA_I/AAAAAAAAAEY/LY2W9VlyQg8/s1600/linear+mapping.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Visualizing a Linear Mapping</td></tr>
</tbody></table>
Very often we need to "map" one set of values to another. For example, if we have a slider that ranges from 0 to 1, and we want to use it to control the value of a frequency setting. Or perhaps we have the output of a sine wave (which ranges from -1 to 1) and we want to use that to control the intensity of a EQ. In these cases and many more, we can use a linear mapping to get from one range of values to another.<br />
<br />
A linear mapping is simply a linear equation, such as <span style="font-family: Courier New, Courier, monospace;">y = mx + b</span>, that takes an input, your slider value for example, and gives you back an output. The input is <span style="font-family: Courier New, Courier, monospace;">x</span>, and the output is <span style="font-family: Courier New, Courier, monospace;">y</span>. The trick is to find the values of <span style="font-family: Courier New, Courier, monospace;">m</span> and <span style="font-family: Courier New, Courier, monospace;">b</span>.<br />
<br />
Let's take a concrete example. Let's say you have the output of a sine wave (say from an LFO) that oscillates between -1 and 1. Now we want to use those values to control a frequency setting from 200 to 2000. In this case, <span style="font-family: Courier New, Courier, monospace;">x</span> from the equation above represents the oscillator, and <span style="font-family: Courier New, Courier, monospace;">y</span> represents the frequency setting.<br />
<br />
We know two things: we want <span style="font-family: Courier New, Courier, monospace;">x=-1</span> to map to <span style="font-family: Courier New, Courier, monospace;">y=200</span>, and <span style="font-family: Courier New, Courier, monospace;">x=1</span> to map to <span style="font-family: Courier New, Courier, monospace;">y=2000</span>. Since our original equation, <span style="font-family: Courier New, Courier, monospace;">y = mx + b</span>, had two unknowns (<span style="font-family: Courier New, Courier, monospace;">m</span> and <span style="font-family: Courier New, Courier, monospace;">b</span>), we can solve it:<br />
<br />
Original equation with both unknowns:<br />
<span style="font-family: Courier New, Courier, monospace;">y = mx + b</span><br />
<br />
Substituting our known values for <span style="font-family: Courier New, Courier, monospace;">x</span> and <span style="font-family: Courier New, Courier, monospace;">y</span>:<br />
<span style="font-family: Courier New, Courier, monospace;">200 = (-1)m + b</span><br />
<span style="font-family: Courier New, Courier, monospace;">2000 = (1)m + b</span><br />
<br />
Solving for <span style="font-family: Courier New, Courier, monospace;">b</span>:<br />
<span style="font-family: Courier New, Courier, monospace;">2200 = 2b</span><br />
<span style="font-family: Courier New, Courier, monospace;">1100 = b</span><br />
<br />
Solving for <span style="font-family: Courier New, Courier, monospace;">m</span>:<br />
<span style="font-family: Courier New, Courier, monospace;">2000 = m + 1100</span><br />
<span style="font-family: Courier New, Courier, monospace;">900 = m</span><br />
<br />
Final equation:<br />
<span style="font-family: Courier New, Courier, monospace;">y = 900x + 1100</span><br />
<br />
You can check the final equation by substituting -1 and 1 for <span style="font-family: Courier New, Courier, monospace;">x</span> and making sure you get 200 and 2000 respectively for <span style="font-family: Courier New, Courier, monospace;">y</span>.<br />
<br />
So in our LFO/frequency example, we would take our LFO value, say .75, and use that as x. Then plug that value into the formula (y=900(.75) + 1100=1775) and get our final value for our frequency setting.<br />
Bjorn Rochehttp://www.blogger.com/profile/17072425815152893296noreply@blogger.com0tag:blogger.com,1999:blog-7225698277211840079.post-42447870940913216602013-07-21T07:43:00.001-07:002013-08-07T10:41:12.417-07:00Peak Meters, dBFS and Headroom<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="http://4.bp.blogspot.com/-Hwhn0tZB8I4/Uevn4E5VKLI/AAAAAAAAADY/lYBZKI1EU4Q/s1600/level_meter_horizontal.gif" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" src="http://4.bp.blogspot.com/-Hwhn0tZB8I4/Uevn4E5VKLI/AAAAAAAAADY/lYBZKI1EU4Q/s320/level_meter_horizontal.gif" height="129" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The level meter from audiofile engineering's<br />
<a href="http://www.audiofile-engineering.com/spectre/">spectre</a> program accurately shows peak values<br />
in dBFS</td></tr>
</tbody></table>
Level meters are one of the most basic features of digital audio software. In software, they are very often implemented as peak meters, which are designed to track the maximum amplitude of the signal. Other kinds of meters, such as VU meters, are often simulations of analog meters. Loudness meters, which attempt to estimate our perception of volume rather than volume itself, are also becoming increasingly common. You may also come across RMS and average meters. In this post, I'm only going to talk about peak meters.<br />
<h3>
Peak Meters</h3>
Peak meters are useful in digital audio because they show the user information that is closely associated with the limits of the medium and because they are efficient and easy to implement. Under normal circumstances, we can expect peak meters to correspond pretty well with our perception of volume, but not perfectly. The general expectation users have when looking at peak meters is that if a signal goes above a certain level at some point, that level should be indicated on the meters. In other words, if the signal goes as high as, say -2 dBFS, over some time period, then someone watching the peak meter during that time will see the meter hit the -2 dBFS mark (see below for more on dBFS). Many peak meters have features such as "peak hold" specifically designed so that the user does not need to stare at the meter.<br />
<br />
Beyond that, there are rarely any specifics. Some peak meters show their output linearly, some show their output in dB. Some use virtual LEDs, some a bar graph. In general, if there is a numeric readout or units associated with the meter, the unit should be dBFS.<br />
<br />
Now that we know the basics of peak meters, let's figure out how to implement them.<br />
<h3>
Update Time</h3>
Peak meters should feel fast and responsive. However, they don't update instantly. In software, it is not uncommon to have audio samples run at 44100 samples per second while the display refreshes at only 75 times per second, so there is absolutely no point in showing the value of each sample (not to mention the fact that our eyes couldn't keep up). Clearly we need to figure out how to represent a large number of samples with only one value. For peak meters, we do this as follows:<br />
<br />
<ol>
<li>Figure out how often we want to update. For example, every 100 ms (.1s) is a good starting point, and will work well most of the time.</li>
<li>Figure out how many samples we need to aggregate for each update. If we are sampling at 44100 Hz, a common rate, and want to update every .1s, we need N = 44100 * .1 = 4410 samples per update.</li>
<li>Loop on blocks of size N. Find the peak in each block and display that peak. If the graphics system does not allow us to display a given peak, the next iteration should display the max of any undisplayed peaks.</li>
</ol>
<h3>
Finding the Peak</h3>
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="http://1.bp.blogspot.com/-kvyZ2_g1aX4/UevoppbFXVI/AAAAAAAAADk/novw4OjuOpo/s1600/loudspeaker-waveform.gif" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" src="http://1.bp.blogspot.com/-kvyZ2_g1aX4/UevoppbFXVI/AAAAAAAAADk/novw4OjuOpo/s320/loudspeaker-waveform.gif" height="150" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Sound is created by air pressure swing both above<br />
below the mean pressure.</td></tr>
</tbody></table>
<div>
Finding the peak of each block of N samples is the core of peak metering. To do so, we can't simply find the maximum value of all samples because sound waves contain not just peaks, but also troughs. If those troughs go further from the mean than the peaks, we will underestimate the peak.</div>
<div>
<br /></div>
<div>
The solution to this problem is simply to take the absolute value of each sample, and then find the max of those absolute values. In code, it would look something like this:</div>
<div>
<br />
<br />
<br /></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">float max = 0;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">for( int i=0; i<buf.size(); ++i ) {<n font="" i=""></n></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> const float v = abs( buf[i] )</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> if( v > max )</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> max = v;</span><br />
<span style="font-family: Courier New, Courier, monospace;">}</span></div>
<div>
<br /></div>
<div>
At the end of this loop, max is your peak value for that block, and you can display it on the meter, or, optionally, calculate its value in dBFS first.</div>
<h3>
Calculating dBFS or Headroom</h3>
<div>
(For a more complete and less "arm wavy" intro to decibels, try <a href="http://www.animations.physics.unsw.edu.au/jw/dB.htm">here</a> or <a href="http://en.wikipedia.org/wiki/Decibel">here</a>.) The standard unit for measuring audio levels is the decibel or dB. But the dB by itself is something of an incomplete unit, because, loosely speaking, instead of telling you the amplitude of something, dB tells you the amplitude of something relative to something else. Therefore, to say something has an amplitude of 3dB is meaningless. Even saying it has an amplitude of 0dB is meaningless. You always need some point of reference. In digital audio, the standard point of reference is "Full Scale", ie, the maximum value that digital audio can take on without clipping. If you are representing your audio as a float, 0 dB is nominally calibrated to +/- 1.0. We call this scale dBFS. To convert the above max value (which is always positive because it comes from an absolute value) to dBFS use this formula:</div>
<div>
<br /></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">dBFS = 20 * log10(max);</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: inherit;">You may find it odd that the loudest a signal can normally be is 0 dBFS, but this is how it is. You may find it useful to think of dBFS as "headroom", ie, answering the question "how many dB can I add to the signal before it reaches the maximum?" (Headroom is actually equal to -dBFS, but I've often seen headroom labeled as dBFS when the context makes it clear.)</span></div>
Bjorn Rochehttp://www.blogger.com/profile/17072425815152893296noreply@blogger.com1tag:blogger.com,1999:blog-7225698277211840079.post-62303224087015005322013-05-30T18:16:00.000-07:002013-07-13T07:26:04.923-07:00The ABCs of PCM (Uncompressed) digital audioDigital audio can be <a href="http://en.wikipedia.org/wiki/Audio_file_format">stored in a wide range of formats</a>. If you are a developer interested in doing anything with audio, whether it's changing the volume, editing chunks out, looping, mixing, or adding reverb, you absolutely must understand the format you are working with. That doesn't mean you need to understand all the details of the <i>file</i> format, which is just a container for the audio which can be read by a library. It does mean you need to understand the <i>data</i> format you are working with. This blog post is designed to give you an introduction to working with audio data formats.<br />
<h3>
Compressed and Uncompressed Audio</h3>
<div>
Generally speaking, audio comes in two flavors: compressed and uncompressed. Compressed audio can further be subdivided into different kinds of compression: lossless, which preserves the original content exactly, and lossy which achieves more compression at the expense of degrading the audio. Of these, lossy is by far the most well known and includes MP3, AAC (used in iTunes), and Ogg Vorbis. Much information can be found online about the various kinds of lossy and lossless formats, so I won't go into more detail about compressed audio here, except to say that there are many kinds of compressed audio, each with many parameters.<br />
<br /></div>
<div>
Uncompressed PCM audio, on the other hand, is defined by two parameters: the <i>sample rate</i> and the <i>bit-depth</i>. Loosely speaking, the sample rate limits the maximum frequency that can be represented by the format, and the bit-depth determines the maximum dynamic range that can be represented by the format. You can think of bit-depth as determining how much noise there is compared to signal.</div>
<div>
<br />
CD audio is uncompressed and uses a 44,100 Hz sample rate and 16 bit samples. What this means is that audio on a CD is represented by 44,100 separate measurements, or samples, taken per second. Each sample is stored as a 16-bit number. Audio recorded in studios often use a bit depth of 24 bits and sometimes a higher sample rate.<br />
<br /></div>
<div>
<div>
WAV and AIFF files support both compressed and uncompressed formats, but are so rarely used with compressed audio that these formats have become synonymous with uncompressed audio. The most common WAV files use the same parameters as CD audio: 44,100 Hz and bit depth of 16-bits, but other sample rates and bit depths are supported.</div>
</div>
<h3>
Converting From Compressed to Uncompressed Formats</h3>
<div>
As you probably already know, lots of audio in the world is stored in compressed formats like MP3. However, it's difficult to do any kind of meaningful processing on compressed audio. So, in order to change a compressed file, you must uncompress, process, and re-compress it. Every compression step results in degradation, so compressing it twice results in extra degradation. You can use lossless compression to avoid this, but the extra compression and decompression steps are likely to require a lot of CPU time, and the gains from compression will be relatively minor. For this reason, compressed audio is usually used for delivery and uncompressed audio is usually used in intermediate steps.</div>
<div>
<br /></div>
<div>
However, the reality is that sometimes we process compressed audio. Audiofiles and music producers may scoff, but sometimes that's life. For example, it you are working on mobile applications with limited storage space, telephony and VOIP applications with limited bandwidth, and web applications with many free users, you might find yourself need to store intermediate files in a compressed format. Usually the first step in processing compressed audio, like MP3, is to decompress it. This means converting the compressed format to PCM. Doing this involves a detailed understanding of the specific format. I recommend using a library such as <a href="http://www.mega-nerd.com/libsndfile/">libsoundfile</a>, <a href="http://www.ffmpeg.org/">ffmpeg</a> or <a href="http://lame.sourceforge.net/">lame</a> for this step.</div>
<h3>
Uncompressed Audio</h3>
<div>
Most stored, uncompressed audio is 16-bit. Other bit depths, like 8 and 24 are also common and many other bit-depths exist. Ideally, intermediate audio would be stored in floating point format, as is supported by both WAV and AIFF formats, but the reality is that almost no one does this.<br />
<br /></div>
<div>
Because 16-bit is so common, let's use that as an example to understand how the data is formatted. 16-bit audio is usually stored as packed 16-bit signed integers. The integers may be big-endian (most common for AIFF) or little-endian (most common for WAV). If there are multiple channels, the channels are usually interleaved. For example, in stereo audio (which has two channels, left and right), you would have one 16-bit integer representing the left channel, followed by one 16-bit integer representing the right channel. These two samples represent the same time and the two together are sometimes called a sample frame or simply a frame.<br />
<br /></div>
<div>
<table border="1" cellpadding="0" cellspacing="0" style="width: 100%;">
<tbody>
<tr width="50%">
<td>Sample Frame 1:<br />
<table border="1" cellpadding="0" cellspacing="0" style="width: 100%;">
<tbody>
<tr><td></td><td width="25%">Left MSB</td>
<td width="25%">Left LSB</td>
<td width="25%">Right MSB</td>
<td width="25%">Right LSB</td>
</tr>
</tbody></table>
</td>
<td>Sample Frame 2:<br />
<table border="1" cellpadding="0" cellspacing="0" style="width: 100%;">
<tbody>
<tr><td></td><td width="25%">Left MSB</td>
<td width="25%">Left LSB</td>
<td width="25%">Right MSB</td>
<td width="25%">Right LSB</td>
</tr>
</tbody></table>
</td>
</tr>
</tbody></table>
</div>
<div>
2 sample frames of big-endian, 16-bit interleaved audio. Each box represents one 8-bit byte.<br />
<br />
The above example shows 2 sample frames of big-endian, 16-bit interleaved audio. You can tell it's big-endian because the most significant byte (MSB) comes first. It's 16-bit because 2 8-bit bytes make up a single sample. It's interleaved because each left sample is followed by a corresponding right sample in the same frame.<br />
<br />
In Java, and most C environments, a 16 bit signed integer is represented with the <span style="font-family: Courier New, Courier, monospace;">short</span> datatype. Therefore, to read raw 16 bit data, you will usually want to get the data into an array of <span style="font-family: Courier New, Courier, monospace;">short</span>s. If you are only dealing with C, you can do your IO directly with <span style="font-family: Courier New, Courier, monospace;">short</span> arrays, or simply use casting or type punning from a raw <span style="font-family: Courier New, Courier, monospace;">char</span> array. In Java, you can use <span style="font-family: Courier New, Courier, monospace;">readShort()</span> from <a href="http://docs.oracle.com/javase/6/docs/api/java/io/DataInputStream.html"><span style="font-family: Courier New, Courier, monospace;">DataInputStream</span></a>.<br />
<br />
To store 16-bit stereo interleaved audio in C, you might use a structure like this:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">struct {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> short l;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> short r;</span><br />
<span style="font-family: Courier New, Courier, monospace;">} stereo_sample_frame_t ;</span><br />
<br />
or you might simply have an array of shorts:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">short samples[];</span><br />
<br />
In the latter case, you would just need to be aware that when you index an even number it's the left channel, and when you index an odd number it's the right channel. Iterating through all your data and finding the max on each channel would look something like this:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">int sampleCount = ...//total number of samples = sample frames * channels</span><br />
<span style="font-family: Courier New, Courier, monospace;">int frames = sampleCount / 2 ;</span><br />
<span style="font-family: Courier New, Courier, monospace;">short samples[]; //filled in elsewhere</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">short maxl = 0;</span><br />
<span style="font-family: Courier New, Courier, monospace;">short maxr = 0;</span><br />
<span style="font-family: Courier New, Courier, monospace;">for( int i=0; i<SIZE; ++i )<frames font="" i=""></frames></span><br />
<span style="font-family: Courier New, Courier, monospace;"> maxl = (short) MAX( maxl, abs( samples[2*i] ) );</span><br />
<span style="font-family: Courier New, Courier, monospace;"> maxr = (short) MAX( maxr, abs( samples[r*i+1] ) );</span><br />
<span style="font-family: Courier New, Courier, monospace;">}</span><br />
<span style="font-family: Courier New, Courier, monospace;">printf( "Max left %d, Max right %d.", maxl, maxr );</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
Note how we find the absolute value of each sample. Usually when we are interested in the maximum, we are looking for the maximum deviation from zero, and we don't really care if it's positive or negative -- either way is going to sound equally loud.<br />
<h3>
Processing Raw Data</h3>
You may be able to do all the processing you need to do in the native format of the file. For example, once you have an array of <span style="font-family: Courier New, Courier, monospace;">short</span>s representing the data, you could divide each short by two to cut the volume in half:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">int sampleCount; //total number of samples = sample frames * channels</span><br />
<span style="font-family: Courier New, Courier, monospace;">short samples[]; //filled in elsewhere</span><br />
<br />
<span style="font-family: Courier New, Courier, monospace;">for( int i=0; i<size font="" i="" samplecount=""></size></span></div>
<span style="font-family: Courier New, Courier, monospace;"> samples[i] /= 2 ;</span><br />
<span style="font-family: Courier New, Courier, monospace;">}</span><br />
<br />
<br />
A few things to watch out for:<br />
<br />
<ul>
<li>You must actually use the native format of the file or the proper conversion. You can't simply deal with the data as a stream of bytes. I've seen many questions on stack overflow where people make the mistake of dealing with 16-bit audio data byte-by-byte, even though each sample of 16-bit audio is composed of 2 bytes. This is like adding a multidigit number without the <a href="http://en.wikipedia.org/wiki/Carry_(arithmetic)">carry</a>.</li>
<li>You must watch out for overflow. For example, when increasing the volume, be aware that some samples my end up out of range. You must ensure that all samples remain in the correct range for their datatype. The simplest way to handle this is with clipping (discussed below), which will result in some distortion, but is better than "wrap-around" that will happen otherwise. (the example above does not have to watch out for overflow because we are dividing not multiplying.)</li>
<li>Round-off error is virtually inevitable. If you are working in an integer format, eg 16-bit, it is almost impossible to deal with roundoff error. The effects of round-off will be minor but ugly. Eventually these errors will accumulate and be noticeable The example above will definitely have problems with roundoff error.</li>
</ul>
As long as studio quality isn't your goal, however, you can mix, adjust volume and do a variety of other basic operations without needing to worry too much.<br />
<h3>
Converting and Using Floating Point Samples</h3>
<div>
If you need more powerful or flexible processing, you are probably going to want to convert your samples to floating point. Generally speaking, the nominal range used for audio when audio is represented as floating point numbers is [-1,1].</div>
<div>
<br /></div>
<div>
You don't have to abide by this convention. If you like, you can simply convert your raw data to float by casting:</div>
<div>
<br /></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">short s = ... // raw data</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">float f = (float) s;</span></div>
<div>
<br /></div>
<div>
But if you have some files that are 16-bit and some that are 24-bit or 8-bit, you will end up with unexpected results:</div>
<div>
<br /></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">char d1 = ... //data from 8-bit file</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">float f1 = (float) d1; </span><span style="font-family: 'Courier New', Courier, monospace;">// now in range [ -128, 127 ]</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">short d2 = ... //data from 16-bit file</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">float f2 = (float) d2; </span><span style="font-family: 'Courier New', Courier, monospace;">// now in range [ -32,768, 32,767 ]</span></div>
<div>
<br /></div>
<div>
It's hard to know how to use <span style="font-family: Courier New, Courier, monospace;">f1</span> and <span style="font-family: Courier New, Courier, monospace;">f2</span> together since their ranges are so different. For example, if you want to mix the two, you most likely won't be able to hear the 8-bit file. This is why we usually scale audio into the [-1,1] range.</div>
<div>
<br /></div>
<div>
There is much <a href="http://blog.bjornroche.com/2009/12/int-float-int-its-jungle-out-there.html">debate</a> about the right constants to use when scaling your integers, but it's hard to go wrong with this:</div>
<div>
<br /></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">int i = //data from n-bit file</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">float f = (float) i ;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">f /= M;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: Times, Times New Roman, serif;">where </span><span style="font-family: Courier New, Courier, monospace;">M</span><span style="font-family: Times, Times New Roman, serif;"> is </span><span style="font-family: Courier New, Courier, monospace;">2^(n-1)</span><span style="font-family: Times, Times New Roman, serif;">. Now, </span><span style="font-family: Courier New, Courier, monospace;">f</span><span style="font-family: Times, Times New Roman, serif;"> is guaranteed to be in the range [-1,1]. After you've done your processing, you'll usually want to convert back. To do so, use the same constant and check for out of range values:</span></div>
<div>
<span style="font-family: Times, Times New Roman, serif;"><br /></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">float f = // processed data</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">f *= M;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">if( f < - M ) f = -2^(n-1);</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">if( f > M-1) f = M-1;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">i = (int) f;</span></div>
<h3>
<span style="font-family: Times, Times New Roman, serif;">Distortion and Noise</span></h3>
<div>
<span style="font-family: Times, Times New Roman, serif;">It's hard to avoid distortion and noise when processing audio. In fact, unless what you are doing is trivial or represents a special case, noise and/or distortion are inevitable. The key is to minimize it, but doing so is not easy. </span><span style="font-family: Times, 'Times New Roman', serif;">Broadly speaking, noise happens every time you are forced to round and distortion happens when you change values nonlinearly. We potentially created distortion in the code where we converted from a float to an integer with a range check, because any values outside the range boundary would have been treated differently than values inside the range boundary. </span><span style="font-family: Times, 'Times New Roman', serif;">The more of the signal is out of range the more distortion this will introduce.</span><span style="font-family: Times, 'Times New Roman', serif;"> We created noise in the code where we lowered the volume because we introduced round-off error when we divided by two. We also introduce noise when we convert from floating point to integer. In fact, many mathematical operations will introduce noise.</span></div>
<div>
<span style="font-family: Times, 'Times New Roman', serif;"><br /></span></div>
<div>
<span style="font-family: Times, 'Times New Roman', serif;">Any time you are working with integers, you need to watch out for overflows. For example, the following code will mix two input signals represented as an array of shorts. We handle overflows in the same way we did above, by clipping:</span></div>
<div>
<span style="font-family: Times, 'Times New Roman', serif;"><br /></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">short input1[] = ...//filled in elsewhere</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">short input2[] = ...//filled in elsewhere</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">// we are assuming input1 and input2 have size SIZE or greater</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">short output[ SIZE ];</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">for( int i=0; i</span><span style="font-family: 'Courier New', Courier, monospace;"><</span><span style="font-family: 'Courier New', Courier, monospace;">SIZE; ++i )</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> int tmp = (int)</span><span style="font-family: 'Courier New', Courier, monospace;">input1[i] + (int)input2[i];</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> if( tmp > SHRT_MAX ) tmp = SHRT_MAX;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> if( tmp < SHRT_MIN ) tmp = SHRT_MIN;</span><span style="color: #666666; font-family: arial, sans-serif; font-size: x-small; line-height: 15px; white-space: nowrap;"> </span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> output[i] = tmp ;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">}</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: inherit;">If it so happens that the signal frequently "clips", then we will hear a lot of distortion. If we want to get rid of distortion altogether, we can eliminate it by dividing by 2. This will reduce the output volume and introduce some round-off noise, but will solve the distortion problem:</span></div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">for( int i=0; i</span><span style="font-family: 'Courier New', Courier, monospace;"><</span><span style="font-family: Courier New, Courier, monospace;">SIZE; ++i )<size font="" i=""></size></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> int tmp = (int)</span><span style="font-family: 'Courier New', Courier, monospace;">input1[i] + (int)input2[i];</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> tmp /= 2;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> output[i] = tmp ;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">}</span></div>
</div>
<h3>
Notes:</h3>
<div>
A few final notes:</div>
<div>
<ul>
<li>For some reason, WAV files don't support signed 8-bit format, so when reading and writing WAV files, be aware that 8-bits means unsigned, but in virtually all other cases it's safe to assume integers are signed.</li>
<li>Always remember to swap the bytes if the native endian-ness doesn't match the file endian-ness. You'll have to do this again before writing.</li>
<li>When reducing the resolution of data (eg, casting from float to int; multiplying an integer by a non-integer, etc), you are introducing noise because you are throwing out data. It might seem as though this will not make much difference, but it turns out that for sampled data in a time-series (like audio) it has a surprising impact. This impact is small enough that for simple audio applications you probably don't need to worry, but for anything studio-quality you will want to understand something called <a href="http://en.wikipedia.org/wiki/Dither">dither</a>, which is the only correct way to solve the problem.</li>
<li>You may have come across <a href="http://www.vttoth.com/CMS/index.php/technical-notes/68">one of these</a> <a href="http://atastypixel.com/blog/how-to-mix-audio-samples-properly-on-ios/" rel="nofollow">unfortunate posts</a>, which claims to have found a better way to mix two audio signals. Here's the thing: there is no secret, magical formula that allows you to mix two audio signals and keep them both at the same original volume, but have the mix still be within the same bounds. The correct formula for mixing two signals is the one I described. If volume is a problem, you can either turn up the master volume control on your computer/phone/amplifier/whatever or use some kind of processing like a <a href="http://en.wikipedia.org/wiki/Dynamic_range_compression">limiter</a>, which will also degrade your signal, but not as badly as the formula in that post, which produces a terrible kind of distortion (<a href="http://en.wikipedia.org/wiki/Ring_modulation">ring modulation</a>).</li>
</ul>
</div>
Bjorn Rochehttp://www.blogger.com/profile/17072425815152893296noreply@blogger.com25tag:blogger.com,1999:blog-7225698277211840079.post-70429813416482985482012-11-27T08:51:00.002-08:002012-11-27T08:51:57.548-08:00Audio IIR v FIR EQs<br />
Digital filters come in two flavors: IIR (or "Infinite Impulse Response") and FIR (or "Finite Impulse Response"). Those complex acronyms may confuse you, so let's shed a little light on the situation by defining both and explaining the differences.<br />
<br />
Some people are interested in which is better. Unfortunately, as with many things, there is no easy answer to that question, other than "it depends", and sometimes what it depends on is your ears. I won't stray too deep into field of opinions, but I will try to mention why some people claim one is better than the other and what some of the advantages and disadvantages are in different situations.<br />
<h3>
How Filters Work</h3>
When you design a filter, you start with a set of specifications. To audio engineers, this might be a bit vague, like "boost 1 kHz by 3 dB", but electrical engineers are usually trained to design filters with very specific constraints. However you start, there's usually some long set of equations, and rules used to "design" the filter, depending on what type of filter you are designing and what the specific constraints are (to see one way you might design a filter, see this post on <a href="http://blog.bjornroche.com/2012/08/basic-audio-eqs.html">audio eq design</a>). Once the filter is "designed" you can actually process audio samples.<br />
<h3>
IIR Filters</h3>
Once the filter is designed, the filter itself is implemented as difference equations, like this:<br />
<br />
y[i] = a0 * x[i] + a1 * x[i-1] ... + a<i>n</i> * x[i-n] - b1 * y[i-1] ... - b<i>m</i> * y[i-m].<br />
<br />
In this case, y is an array storing the output, and x is an array storing the input. Note that each output is a linear function of previous inputs and outputs, as well as the current input.<br />
<br />
In order to know the current value of y, we need to know the last value of y, and to know that, you must know the value of still earlier values of y, and so on, all the way back until we reach our initial conditions. For this reason, this kind of filter is sometimes called a "recursive" filter. In principle, this filter can be given a finite input, and it will produce output forever. Because its response is infinite, we call this filter an IIR, or "Infinite Impulse Response" filter.<br />
<br />
(To further confuse the terminology, IIR filters are often designed with certain constraints that make them "minimum phase." While IIR filters are not all minimum phase, many people use the terms "recursive", "IIR" and "minimum phase" interchangeably.)<br />
<br />
Digital IIR filters are often modeled after analog filters. In many ways, analog-modled IIR filters sound like analog filters. They are very efficient, too: for audio purposes, they usually only require a few multiplies.<br />
<h3>
FIR Filters</h3>
FIR filters, on the other hand, are usually implemented with a difference equation that looks like this:<br />
<br />
y[i] = a0 * x[i] + a1 * x[i-1] a2 * x[i-2] + ... a<i>n</i> * x[i-n] + a<i>n</i> * x[i-n-1] + ... + a1 * x[2i+1] + a0 * x[2i]<br />
<br />
In this case, we don't use previous outputs: in order to calculate the current output, we only need to know the previous <i>n</i> inputs. This may improve the numerical stability of the filter because roundoff errors are not accumulated inside the filter. However, generally speaking, FIR filters are much more CPU intensive for a comparable response, and have some other problems, such as high latency, and both pass-band and stop-band ripple.<br />
<br />
If an FIR filter can be implemented using a difference equation that is symmetrical, like the one above, it has a special property called "linear phase." Linear phase filters delay all frequencies in the signal by the same amount, which is not possible with IIR filters.<br />
<h3>
Which Filter?</h3>
<div>
When deciding which filter to use, there are many things to take into account. Here are some of those things:</div>
<br />
<ul>
<li>Some people feel that linear phase FIR filters sound more natural and have fewer "artifacts".</li>
<li>FIR filters are usually much more processor intensive for the same response.</li>
<li>FIR filters have "ripple" in both the passband and stopband, meaning the response is "jumpy". IIR filters can be designed without any ripple.</li>
<li>IIR filters can be easily designed to sound like analog filters.</li>
<li>IIR filters require careful design to ensure stability and good numerical error properties, however, that art is fairly advanced.</li>
<li>FIR filters generally have a higher latency.</li>
</ul>
<br />
Bjorn Rochehttp://www.blogger.com/profile/17072425815152893296noreply@blogger.com0tag:blogger.com,1999:blog-7225698277211840079.post-13632060351092459672012-08-23T21:12:00.002-07:002012-08-25T21:16:15.564-07:00Basic Audio EQs<a href="http://blog.bjornroche.com/2012/08/why-eq-is-done-in-time-domain.html">In my last post</a>, I looked at why it's usually better to do EQ (or filtering) in the time domain than the frequency domain as far as audio is concerned, but I didn't spend much time explaining how you might implement a time-domain EQ. That's what I'm going to do now.<br />
<br />
The theory behind time-domain filters could fill a book. Instead of trying to cram you full of theory we'll just skip ahead to what you need to know to do it. I'll assume you already have some idea of what a filter is.<br />
<h3>
Audio EQ Cookbook</h3>
The <a href="http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt">Audio EQ Cookbook</a> by <span style="white-space: pre-wrap;">Robert Bristow-Johnson is a great, albeit very terse, description of how to build basic audio EQs. These EQs can be described as second order digital filters, sometimes called "<a href="http://en.wikipedia.org/wiki/Digital_biquad_filter">biquads</a>"because the equation that describes them contains two quadratics. In audio, we sometimes use other kinds of filters, but second order filters are a real workhorse. First order filters don't do much: they generally just allow us to adjust the overall balance of high and low frequencies. This can be useful in "tone control" circuits, like you might find on some stereos and guitars, but not much else. Second order filters give us more control -- we can "dial in" a specific frequency, or increase or decrease frequencies above and below a certain threshold, with a fair degree of accuracy, for example. If we need even more control than a second order filter offers, we can often simply take several second order filters and place them in series to simulate the effect of a single higher order filter.</span><br />
<span style="white-space: pre-wrap;"><br /></span>
<span style="white-space: pre-wrap;">Notice I said series, though. Don't try putting these filters in parallel, because they not only alter the frequency response, but also the phase response, so when you put them in parallel you might get unexpected results. For example, if you take a so-called all-pass filter and put it in parallel with no filter, the result will not be a flat frequency response, even though you've combined the output of two signals that have the same frequency response as the original signal.</span><br />
<span style="white-space: pre-wrap;"><br /></span>
<span style="white-space: pre-wrap;">Using the Audio EQ Cookbook, we can design a peaking, high-pass, low-pass, band-pass, notch (or band-stop), or shelving filter. These are the basic filters used in audio. </span><span style="white-space: pre-wrap;">We can even design that crazy all-pass filter I mentioned which actually does come in handy if you are building a phaser. (It has other uses, too, but that's for another post.)</span><br />
<h3>
<span style="white-space: pre-wrap;">Bell Filter</span></h3>
<span style="white-space: pre-wrap;">Let's design a "bell", or "peaking" filter using RBJ's cookbook. Most other filters in the cookbook are either similar to the bell or simpler, so once you understand the bell, you're golden. To start with, you will need to know the sample rate of the audio going into and coming out of your filter, and the center frequency of your filter. The center frequency, in the case of the bell filter, is the frequency that "most affected" by your filter. You will also want to define the width of the filter, which can be done in a number of ways usually with some variation on "Q" or "quality factor" and "bandwidth". RBJ's filters define bandwidth in octaves, and you want to be careful that you don't extend the top of the bandwidth above the Niquist frequency (or 1/2 the sample rate), or your filter won't work. We also need to know how much of our center frequency to add in dB (if we want to remove, we just use a negative value, and for no change, we set that to 0).</span><br />
<span style="white-space: pre-wrap;"><br /></span>
<span style="white-space: pre-wrap;"><span style="font-family: Courier New, Courier, monospace;">Fs = Sample Rate</span></span><br />
<span style="white-space: pre-wrap;"><span style="font-family: Courier New, Courier, monospace;">F0 = Center Frequency (always less than Fs/2)</span></span><br />
<span style="white-space: pre-wrap;"><span style="font-family: Courier New, Courier, monospace;">BW = Bandwidth in octaves</span></span><br />
<span style="white-space: pre-wrap;"><span style="font-family: Courier New, Courier, monospace;">g = gain in dB</span></span><br />
<span style="white-space: pre-wrap;"><br /></span>
<span style="white-space: pre-wrap;">Great! Now we are ready to begin our calculations. First, RJB suggests calculating some intermediate values:</span><br />
<span style="white-space: pre-wrap;"><br /></span>
<span style="white-space: pre-wrap;"><span style="font-family: Courier New, Courier, monospace;">A = 10^(g/40)</span></span><br />
<span style="white-space: pre-wrap;"><span style="font-family: Courier New, Courier, monospace;">w0 = 2*pi*f0/Fs
c = cos(w0)
s = sin(w0)
alpha = s*sinh( ln(2)/2 * BW * w0/s )</span></span><br />
<span style="white-space: pre-wrap;"><span style="font-family: Courier New, Courier, monospace;"><br /></span></span>
<span style="white-space: pre-wrap;">This is a great chance to use that hyperbolic</span><span style="font-family: inherit;"><span style="white-space: pre-wrap;"> sin button on your scientific </span></span><span style="white-space: pre-wrap;">calculator</span><span style="font-family: inherit;"><span style="white-space: pre-wrap;"> that, until now, has only been collecting dust. Now that we've done that, we can finally calculate the filter </span></span><span style="white-space: pre-wrap;">coefficients</span><span style="font-family: inherit;"><span style="white-space: pre-wrap;">, which we use when actually processing data:</span></span><br />
<span style="font-family: inherit;"><span style="white-space: pre-wrap;"><br /></span></span>
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;">b0 = 1 + alpha*A
b1 = -2*c
b2 = 1 - alpha*A
a0 = 1 + alpha/A
a1 = -2*c
a2 = 1 - alpha/A</span></span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;"><br /></span></span>
<span style="white-space: pre-wrap;"><span style="font-family: inherit;">Generally speaking, we want to "normalize" these </span></span><span style="white-space: pre-wrap;">coefficients</span><span style="white-space: pre-wrap;"><span style="font-family: inherit;">, so that </span><span style="font-family: Courier New, Courier, monospace;">a0 = 1</span><span style="font-family: inherit;">. We can do this by dividing each coefficient by </span><span style="font-family: Courier New, Courier, monospace;">a0.</span><span style="font-family: inherit;"> Do this in advance or the electrical engineers will laugh at you:</span></span><br />
<span style="white-space: pre-wrap;"><span style="font-family: inherit;"><br /></span></span>
<span style="font-family: 'Courier New', Courier, monospace; white-space: pre-wrap;">b0 /= a0
b1 /= a0
b2 /= a0
a1 /= a0
a2 /= a0</span><br />
<span style="white-space: pre-wrap;"><span style="font-family: Courier New, Courier, monospace;"><br /></span></span>
<span style="white-space: pre-wrap;"><span style="font-family: inherit;">Now, in pseudocode, here's how we process our data, one sample at a time using a "process" function that looks something like this:</span></span><br />
<br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;">number xmem1, xmem2, ymem1, ymem2;</span></span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;"><br /></span></span>
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;">void reset() {</span></span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;"> xmem1 = xmem2 = ymem1 = ymem2 = 0;</span></span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;">}</span></span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;">number process( number x ) {</span></span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;"> number y = b0*x + b1*xmem1 + b2*xmem2 - a1*ymem1 - a2*ymem2;</span></span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;"><br /></span></span>
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;"> xmem2 = xmem1;</span></span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;"> xmem1 = x;</span></span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;"> ymem2 = ymem1;</span></span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;"> ymem1 = y;</span></span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;"><br /></span></span>
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;"> return y;</span></span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;">}</span></span><br />
<br />
You'll probably have some kind of loop that your process function goes in, since it will get called once for each audio sample.<br />
<br />
<span style="font-family: inherit;"><span style="white-space: pre-wrap;">There's actually more than one way to implement the process function given that particular set of coefficients. This implementation is called "Direct Form I" and happens to work pretty darn well most of the time. "Direct form II" has some admirers, but those people are either suffering from graduate-school-induced trauma or actually have some very good reason for doing what they are doing that in all </span></span><span style="white-space: pre-wrap;">likelihood</span><span style="font-family: inherit;"><span style="white-space: pre-wrap;"> does not apply to you. There are of course other implementations, but DFI is a good place to start.</span></span><br />
<span style="white-space: pre-wrap;"><span style="font-family: inherit;"><br /></span></span>
<span style="white-space: pre-wrap;"><span style="font-family: inherit;">You may have noticed that the output of the filter, </span><span style="font-family: Courier New, Courier, monospace;">y</span><span style="font-family: inherit;">, is stored and used as an input to future iterations. The filter is therefore "recursive". This has several implications:</span></span><br />
<br />
<ul>
<li><span style="white-space: pre-wrap;"><span style="font-family: inherit;">The filter is fairly sensitive to errors in the recursive values and coefficients</span></span><span style="white-space: pre-wrap;"><span style="font-family: inherit;">. Because of this, we need to take care of what happens with the error in our </span><span style="font-family: Courier New, Courier, monospace;">y</span><span style="font-family: inherit;"> values. In practice, on computers, we usually just need to use a high resolution floating point value (ie double precision) to store these (on fixed point hardware, it is often another matter).</span></span></li>
<li><span style="white-space: pre-wrap;"><span style="font-family: inherit;">Another issue is that you can't just blindly set the values of your </span></span><span style="white-space: pre-wrap;">coefficients</span><span style="font-family: inherit;"><span style="white-space: pre-wrap;">, or your filter may become unstable. Fortunately, the coefficients that come out of RJB's equations always result in stable filters, but don't go messing around. For example, you might be tempted to interpolate coefficients from one set of values to another to simulate a filter sweep. Resist this temptation or you will unleash the numerical fury of hell! The values in between will be "unstable" meaning that your output will run off to infinity. Madness, </span></span><span style="white-space: pre-wrap;">delirium</span><span style="font-family: inherit;"><span style="white-space: pre-wrap;">, vomiting and broken speakers are often the unfortunate </span></span><span style="white-space: pre-wrap;">casualties</span><span style="font-family: inherit;"><span style="white-space: pre-wrap;">.</span></span></li>
<li><span style="font-family: inherit;"><span style="white-space: pre-wrap;">On some platforms you will have to deal with something called "denormal" numbers. This is a major <a href="http://musicdsp.org/files/denormal.pdf">pain in the ass</a>, I'm sorry to say. Basically it means our performance will be between 10 and 100 times worse than it should be because the CPU is busy calculating tiny numbers you don't care about. This is one of the rare cases where I would advocate optimizing before you measure a problem because sometimes your code moves around and it comes up and it's very hard to trace this issue. In this case, the easiest solution is probably to do something like this (imagine we are in C for a moment):</span></span></li>
</ul>
<span style="white-space: pre-wrap;"><br /></span>
<br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;">#DEFINE IS_DENORMAL(f) (((*(unsigned int *)&(f))&0x7f800000) == 0)</span></span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;">float xmem1, xmem2, ymem1, ymem2;</span></span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;"><br /></span></span>
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;">void reset() {</span></span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;"> xmem1 = xmem2 = ymem1 = ymem2 = 0;</span></span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;">}</span></span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;">float process( float x ) {</span></span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;"> number y = b0*x + b1*xmem1 + b2*xmem2 - a1*ymem1 - a2*ymem2;</span></span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;"><br /></span></span>
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;"> if( IS_DENORMAL( y ) )</span></span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;"> y = 0;</span></span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;"><br /></span></span>
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;"> xmem2 = xmem1;</span></span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;"> xmem1 = x;</span></span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;"> ymem2 = ymem1;</span></span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;"> ymem1 = y;</span></span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;"><br /></span></span>
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;"> return y;</span></span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;">}</span></span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;"><br /></span></span>
<span style="white-space: pre-wrap;"><span style="font-family: inherit;">Okay, happy filtering!</span></span>Bjorn Rochehttp://www.blogger.com/profile/17072425815152893296noreply@blogger.com20tag:blogger.com,1999:blog-7225698277211840079.post-47807127501467926262012-08-08T14:58:00.000-07:002012-09-28T10:21:29.455-07:00Why EQ Is Done In the Time Domain<a href="http://blog.bjornroche.com/2012/08/when-to-not-use-fft.html">In my last post</a>, I discussed how various audio processing may be best done in the frequency or time domain. Specifically, I suggested that EQ, which is a filter that alters the frequency balance of a signal, is best done in the time domain, not the frequency domain. (See my next post if you want to learn <a href="http://blog.bjornroche.com/2012/08/basic-audio-eqs.html">how to implement a time-domain filter</a>.)<br />
<br />
If this seems counter intuitive to you, rest assured you are not alone. I've been following the "audio" and "FFT" tags (among others) on <a href="http://www.stackoverflow.com/">stack overflow</a> and it's clear that many people attempt to implement EQs in the frequency domain, only to find that they run into a variety of problems.<br />
<h2>
Frequency Domain Filters</h2>
Let's say you want to eliminate or reduce high frequencies from your signal. This is called a "low-pass" filter, or, less commonly, a "high-cut" filter. In the frequency domain, high frequencies get "sorted" into designated "bins", where you can manipulate them or even set them to zero. This seems like an ideal way to do low-pass filtering, but lets explore the process to see why it might not work out so well.<br />
<br />
Our first attempt at a low-pass filter, implemented with the FFT might look something like this:<br />
<ul>
<li>loop on audio input</li>
<li>if enough audio is received, perform FFT, which gives us audio in the frequency domain</li>
<ul>
<li>in frequency domain, perform manipulations we want. In the case of eliminating high frequencies, we set the bins representing high frequencies to 0.</li>
<li>perform inverse FFT, to get audio back in time domain</li>
<li>output that chunk of audio</li>
</ul>
</ul>
<br />
But there are quite a few problems with that approach:<br />
<ul>
<li>We must wait for a chunk of audio before we can even begin processing, which means that we will incur latency in our processing. The higher quality filter we want, the more audio we need to wait for. If the input buffer size does not match the FFT size, extra buffering needs to be done.</li>
<li>The FFT, though efficient compared to the DFT (which is the FFT without the "fast" part), performs worse than linear time, and we need to do both the FFT and it's inverse, which is computationally similar. EQing with the FFT is therefore generally very inefficient compared to comparable time-domain filters.</li>
<li>Because our output chunk has been processed in the frequency domain independent of samples in neighboring chunks, the audio in neighboring chunks may not be continuous. One solution is to process the entire file as one chunk (which only works for offline, rather than real-time processing, and is computationally expensive). The better solution is the <a href="http://en.wikipedia.org/wiki/Overlap%E2%80%93add_method">OLA or Overlap Add method</a> but this involves complexity that many people miss when implementing a filter this way.</li>
<li>Filters implemented via FFT, as well as time-domain filters implemented via IFFT, often do not perform the way people expect. For example, many people expect that if they set all values in bins above a certain frequency to 0, then all frequencies above the given frequency will be eliminated. This is not the case. Instead, frequency responses <i>at</i> the bin values will be 0, but the frequency response <i>between</i> those values is free to fluctuate -- and it does fluctuate, often greatly. This fluctuation is called "ripple." There are techniques for reducing ripple but they are complex, and they don't eliminate ripple. Note that, in general, frequencies across the entire spectrum are subject to ripple, so even just manipulating a small frequency band many create ripple across the entire frequency spectrum.</li>
<li>FFT filters suffer from so-called "pre-echo", where the sounds can be heard before the main sound hits. In and of itself, this isn't really a problem, but sounds are "smeared" so badly by many designs, that many in the audio world feel that these filters can effect the impact of transients and stereo imaging if not implemented and used correctly.</li>
</ul>
So it's clear that FFT filters may not be right, or if they are, they involve much more complexity than many people first realize.<br />
<br />
As a side note, one case where it might be worth all that work is a special case of so-called FIR filters (also sometimes called "Linear phase" filters). These are used sometimes in audio production and in other cases. In audio, they are usually used only in mastering because of their high latency and computational cost, but even then, many engineers don't like them (while others swear by them). FIR filters are best implemented in the time domain, as well, until the number of "taps"in the filter becomes enormous, which it sometimes does, and it actually becomes more efficient to implement using an FFT with OLA. FIR filters suffer from many of the problems mentioned above including pre-echo, high computational cost and latency, but they do have some acoustical properties that make them desirable in some applications.<br />
<h2>
Time Domain Filters</h2>
Let's try removing high frequencies in the time domain instead. In the time domain, high frequencies are represented by the parts of the signal that change quickly, and low frequencies are represented as the parts that change slowly. One simple way to remove high frequencies, then, would be to use a moving average filter:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">y(n) = { x(n) + x(n-1) + .... + x(n-M) } / (M+1)</span><br />
<br />
<span style="font-family: inherit;">where </span><span style="font-family: Courier New, Courier, monospace;">x(i)</span><span style="font-family: inherit;"> is your input sample at time </span><span style="font-family: Courier New, Courier, monospace;">i</span><span style="font-family: inherit;">, and </span><span style="font-family: Courier New, Courier, monospace;">y(i)</span><span style="font-family: inherit;"> is your output sample at time </span><span style="font-family: Courier New, Courier, monospace;">i</span><span style="font-family: inherit;">. No FFT required for that (This is not the best filter for removing high frequencies -- in fact we can do WAY better -- but it is my favorite way to illustrate the point. The moving average filter is not uncommon in economics, image processing and other fields partly for this reason.). Several advantages are immediately obvious, and some are not so obvious:</span><br />
<ul>
<li><span style="font-family: inherit;">Each input sample can be processed one at a time to produce one output sample without having to chunk or wait for more audio. Therefore, there are also no continuity issues and minimal latency.</span></li>
<li><span style="font-family: inherit;">It is extremely efficient, with only a few multiplies, adds and memory stores/retrievals required per sample.</span></li>
<li><span style="font-family: inherit;">These filters can be designed to closely mimic analog filters.</span></li>
</ul>
A major disadvantage is that it is not immediately obvious how to design a high-quality filter in the time domain. In fact, it can take some serious math to do so. It's also worth noting that many time-domain filters, like frequency domain filters, also suffer from ripple, but for many design methods, this ripple is well defined and can be limited in various ways.<br />
<br />
In the end, the general rule is that for a given performance, you can get much better results with the time-domain than the frequency domain.Bjorn Rochehttp://www.blogger.com/profile/17072425815152893296noreply@blogger.com8tag:blogger.com,1999:blog-7225698277211840079.post-17639118610607295922012-08-04T09:15:00.003-07:002012-08-04T09:15:47.475-07:00When to (not) use the FFT<a href="http://blog.bjornroche.com/2012/07/frequency-detection-using-fft-aka-pitch.html">In the last post</a> I discussed one use for the FFT: pitch tracking. I also mentioned that there were better ways to do pitch tracking. Indeed, aside from improvements on that method, you could also use entirely different methods that don't rely on the FFT at all.<br />
<br />
The FFT transforms data into the "frequency domain", or, if your data is broken down into chunks, the FFT transforms it into the "time-frequency domain," which we often still think of as the frequency domain. However, the most basic "domain" you can work in is usually the "time domain." In the time domain, audio is represented as sequence of amplitude values. You may know this as "PCM" audio. This is what's usually stored in WAVs and AIFs, and when we access audio devices like soundcards, this is the most natural way to transfer data. It turns out we can also do a whole lot of processing and analysis in the time domain as well.<br />
<br />
<table bgcolor="#dddddd" border="0" cellpadding="4" cellspacing="0" frame="hsides" width="100%">
<tbody>
<tr><th>Process</th><th>Time Domain</th><th>Frequency Domain</th></tr>
<tr><td>Filtering/<br />
EQ</td><td bgcolor="#ddffdd">Yes!</td><td bgcolor="#ffdddd">No!</td></tr>
<tr><td>Pitch Shifting</td><td bgcolor="#ffffdd">Okay</td><td bgcolor="#ffffdd">Okay</td></tr>
<tr><td>Pitch Tracking</td><td bgcolor="#ffffdd">Okay</td><td bgcolor="#ffffdd">Okay</td></tr>
<tr><td>Reverb<br />
(Simulated)</td><td bgcolor="#ddffdd">Yes!</td><td bgcolor="#ffdddd">No!</td></tr>
<tr><td>Reverb<br />
(Impulse)</td><td bgcolor="#ffdddd">No!</td><td bgcolor="#ddffdd">Yes!</td></tr>
<tr><td>Guitar effects<br />
Chorus/flanger/distortion/etc</td><td bgcolor="#ddffdd">Yes!</td><td bgcolor="#ffdddd">No!</td></tr>
<tr><td>SR Conversion</td><td bgcolor="#ddffdd">Yes!</td><td bgcolor="#ffdddd">No!</td></tr>
<tr><td>Compression</td><td bgcolor="#ddffdd">Yes!</td><td bgcolor="#ffdddd">No!</td></tr>
<tr><td>Panning, Mixing, etc</td><td bgcolor="#ddffdd">Yes!</td><td bgcolor="#ffdddd">No!</td></tr>
</tbody><caption>Table 1: Recommendations for Audio Processing in the Time Domain vs. the Frequency Domain</caption>
</table>
<br />
<br />
Wow, so impulse reverb is really the only thing on that list you need an FFT for? Actually even that can be done in the time domain, it's just much more efficient in the frequency domain (so much so that it might be considered impossible in the time domain).<br />
<br />
You might wonder how to adjust the frequency balance of a signal, which is what an EQ does, in the time domain rather than the frequency domain. Well, you <i>can</i> do it in the frequency domain, but you are asking for trouble. I'll talk about this in my next post.Bjorn Rochehttp://www.blogger.com/profile/17072425815152893296noreply@blogger.com1tag:blogger.com,1999:blog-7225698277211840079.post-61514722129569357072012-07-22T18:45:00.001-07:002017-02-23T11:31:45.831-08:00Frequency detection using the FFT (aka pitch tracking) With Source Code<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="http://1.bp.blogspot.com/-4hK5HJz3Z3k/UelNne2ktPI/AAAAAAAAADI/k9WFYnx6KHY/s1600/new_fft2.gif" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" height="240" src="https://1.bp.blogspot.com/-4hK5HJz3Z3k/UelNne2ktPI/AAAAAAAAADI/k9WFYnx6KHY/s320/new_fft2.gif" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">It's not necessarily as simple a it seems to find the pitch<br />
from an FFT. Some pre-processing is required as well<br />
as some knowledge of how the data is organized.</td></tr>
</tbody></table>
How to track pitch with the FFT seems to be a very commonly asked question on <a href="http://stackoverflow.com/">stack overflow</a>. Many people seem to think tracking pitch is as simple as putting your data into an FFT, and looking at the result. Unfortunately, this is not the case. Simply applying an FFT to your input, even if you know what size FFT to use, is not going to give you optimal results, although it might work in some cases.<br />
<br />
At the end of the day, using the FFT is not actually the best pitch tracking method available for tracking or detecting pitch of an audio signal. While it is possible to make a good pitch tracker using the FFT, doing it right requires a tremendous amount of work. The algorithm shown here works, and works pretty well, but if you need something that converges on the correct pitch really quickly, is very accurate, or tracks multiple notes simultaneously, you need something else.<br />
<br />
Still, you can create a decent pitch tracking algorithm that's reasonably easy to understand using the FFT. It doesn't require too much work, and I've explained it and provided code, in the form of a command-line C <a href="https://github.com/bejayoharen/guitartuner">guitar tuner</a> app which you can get from github. It compiles and runs on Mac OS X and you should be able to get it to run on other platforms without much trouble. If you want to port to other languages, that shouldn't be too hard either. It's worth noting that I specifically designed this app to be similar to the tuner described by Craig A. Lindley in <a href="http://www.amazon.com/Digital-Audio-Java-Craig-Lindley/dp/0130876763">Digital Audio with Java</a>, so if you are looking for Java source code, you can check out his code (although there are differences between hi code and mine).<br />
<h2>
The Big Picture</h2>
<div>
To do our pitch detection, we basically loop on the following steps:</div>
<br />
<ol>
<li>Read enough data to fill the FFT</li>
<li>Low-pass the data</li>
<li>Apply a window to the data</li>
<li>Transform the data using the FFT</li>
<li>Find the peak value in the transformed data</li>
<li>Compute the peak frequency from from the index of the peak value in the transformed data</li>
</ol>
<br />
This is the main processing loop for the tuner, with some stuff left out:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">while( running )</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> {</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> // read some data</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> err = Pa_ReadStream( stream, data, FFT_SIZE );</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> // low-pass</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> for( int j=0; j<fft_size font="" j=""></fft_size></span><span style="font-family: "courier new" , "courier" , monospace;"><</span><span style="font-family: "\22 courier new\22 " , "\22 courier\22 " , monospace;">FFT_SIZE; ++j ) {</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> data[j] = processSecondOrderFilter( data[j], mem1, a, b );</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> data[j] = processSecondOrderFilter( data[j], mem2, a, b );</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> // window</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> applyWindow( window, data, FFT_SIZE );</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> // do the fft</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> for( int j=0; j</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> datai[j] = 0;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> applyfft( fft, data, datai, false );</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> //find the peak</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> float maxVal = -1;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> int maxIndex = -1;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> for( int j=0; j<</span><span style="font-family: "\22 courier new\22 " , "\22 courier\22 " , monospace;">FFT_SIZE; ++j ) {</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> float v = data[j] * data[j] + datai[j] * datai[j] ;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if( v > maxVal ) {</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> maxVal = v;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> maxIndex = j;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> float freq = freqTable[maxIndex];</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> //...</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<br />
Let's go over each of the steps and see how they work.<br />
<h2>
Audio Data</h2>
We always need to start with a sequence of numbers representing the amplitude of audio over time (sometimes called "Linear, PCM audio"). This is what we get from most uncompressed audio formats like AIFF and WAV. Its also what you get from audio APIs like ASIO, CoreAudio and ALSA. In this case, we are using <a href="http://portaudio.com/">PortAudio</a>, which acts like a portable wrapper around these and other APIs. If you have a compressed format such as MP3 or OGG, you will have to convert it to uncompressed audio first.<br />
<br />
Your data might be 16-bit integer, 8-bit integer, 32-bit floating point or any number of other formats. We'll assume you know how to get your data to floating point representation in the range from -1 to 1. PortAudio takes care of this for us when we specify these input parameters:<br />
<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">inputParameters.device = Pa_GetDefaultInputDevice();</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> inputParameters.channelCount = 1;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> inputParameters.sampleFormat = paFloat32;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultHighInputLatency ;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> inputParameters.hostApiSpecificStreamInfo = NULL;</span><br />
<br />
<br />
You'll also need to know how often your audio is sampled. For a tuner, less is more, so we'll use a sample rate of 8 kHz, which is available on most hardware. This is extremely low for most audio applications (44.1 kHz is considered standard for audio and 48 kHz is standard for video), but for a tuner, 8 kHhz is plenty.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">#define SAMPLE_RATE (8000)</span><br />
<br />
<h2>
Low-Pass Filtering</h2>
There's no hard and fast rule about low-pass filtering (or simply "low-passing") your audio data. In fact, it's not even strictly necessary, but doing so can get rid of unwanted noise and the higher frequencies that sometimes masquerade as the fundamental frequency. This is important because some instruments have component frequencies called harmonics that are more powerful than the "fundamental" frequencies, and usually we are interested in the fundamental frequencies. Filtering, therefore, can improve the reliability of the rest of the pitch tracker significantly. Without filtering, some noise might appear to be the dominant pitch, or, more likely, the dominant pitch might appear to be a harmonic of the actual fundamental frequency.<br />
<br />
A good choice for the filter is a low-pass filter with a center frequency around or a little above the highest pitch you expect to detect. For a guitar tuner, this might be the high E string, or about 330 Hz. So that's what we'll use -- in fact, we low-pass it twice. If you are modifying the code for another purpose, you can set the center frequency to something that makes sense for your application.<br />
<br />
If you aren't sure or you want to go with or want something less agressive, you could try a moving average filter, which simply outputs the average of the current input and some number of previous inputs. Intuitively, we can understand that this filter reduces high frequencies because signals that change quickly get "smoothed" out.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">// Process every sample of your input with this function</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">// (this is not used in our guitar tuner)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">function float twoPointMovingAverageFilter( float input ) {</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> static float lastInput = 0;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> float output = ( input + lastInput ) / 2 ;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> lastInput = input;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> return output;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">}</span><br />
<br />
The moving average filter won't make a huge difference, but if the low pass filter I used in my code doesn't suit you and you don't have the degree in electrical engineering required to design the right digital filter (or don't know what the right filter is), it might be better than nothing. I haven't tested the moving average filter myself.<br />
<h2>
Windowing</h2>
Generally speaking, FFTs work in chunks of data, but your input is a long or even continuous stream. To fit this round peg into this square hole, you need to break off chunks of your input, and process the chunks. However, doing so without proper treatment may prove detrimental to your results. In rough terms, the problem is that the edges get lopped off very sloppily, creating artifacts at frequencies that aren't actually present in your signal. These artifacts, called "sidelobes", cause problems for many applications. I know that some tuners are designed without special treatment, so you can skip this step, but I strongly recommend you keep reading because it's easy to deal with this problem.<br />
<br />
To reduce the sidelobes, we premultiply each chunk of audio with another signal called a window, or window function. Two simple and popular choices for window functions are the <a href="http://en.wikipedia.org/wiki/Window_function#Hamming_window">Hamming window</a>, and the <a href="http://en.wikipedia.org/wiki/Hann_function">Hann window</a>. I put code for both in the tuner, but I used the Hann window.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">void buildHanWindow( float *window, int size )</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">{</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> for( int i = 0 to size )</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> window[i] = .5 * ( 1 - cos( 2 * M_PI * i / (size-1.0) ) );</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">}</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">void applyWindow( float *window, float *data, int size )</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">{</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> for( int i = 0 to size )</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> data[i] *= window[i] ;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">}</span><br />
<br />
For a tuning app, the windows may overlap, or there may be gaps in between them, depending on your needs and your available processing power. For example, by overlapping and performing more FFTs, and then averaging the results, you may get more accurate results more quickly, at the cost of more CPU time. <b>I strongly recommend doing this in real apps. I did not do this in my app to make the code easier to follow, and you'll see that the values sometimes jump around and don't respond smoothly.</b><br />
<h2>
FFT</h2>
The FFT, or Fast Fourier Transform, is an algorithm for quickly computing the frequencies that comprise a given signal. By quickly, we mean O( N log N ). This is way faster than the O( N<sup>2</sup>) which how long the Fourier transform took before the "fast" algorithm was worked out, but still not linear, so you are going to have to be mindful of performance when you use it. Because the FFT is now the standard way to compute the Fourier transform, many people often use the terms interchangeably, even though this is not strictly correct.<br />
<br />
The FFT works on a chunk of samples at a time. You don't get more or less data out of a Fourier Transform than you put into it, you just get it in another form. That means that if you put ten audio samples in you get ten data-points out. The difference is that these ten data points now represent energy at different frequencies instead of energy at different times, and since our data uses real numbers, and not complex, the FFT will contain some redundancies -- specifically, only the first half of the spectrum contains relevant data. That means that for ten samples in, we really only get five relevant data-points out.<br />
<br />
Clearly, the more frequency resolution you need, the more time data you need to give it. However, at some point you will run into the problem of not being able to return results quickly enough, either because you are waiting for more input, or because it takes too long to process. Choosing the right size FFT is critical: too big and you consume lots of CPU and delay getting a response, too small and your results lack resolution.<br />
<br />
How do we know how big our FFT should be? You can determine the accuracy of your FFT with this simple formula:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">binSize = sampleRate/N ;</span><br />
<br />
For example, with a bin size of 8192 (most implementations of the FFT work best with powers of 2), and a sample rate of 44100, you can expect to get results that are accurate to within about 5.38 Hz. Not great for a tuner, but, hey, that's why we are sampling at 8000 Hz, which gives us an accuracy of better than 1 Hz. Still not perfect, for, say, a 5 string bass, but you can always use a a larger N if you need to. Keep in mind that getting enough samples to get that much accuracy takes longer than a second, so our display only updates about once a second. That's yet another reason you might want to overlap your windows.<br />
<br />
The output of the FFT is an array of N complex numbers. It is possible to use both the real and imaginary part to get very accurate frequency information, but for now we'll settle for something simpler and much easier to understand: we simply look at the magnitude. To find the magnitude of each frequency component, we use the distance formula:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">for( i in 0 to N/2 )</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> magnitude[i] = sqrt( real[i]*real[i] + cmpx[i]*cmpx[i] );</span><br />
<br />
Now that we know the magnitude of each FFT bin, finding the frequency is simply a matter of finding the bin with the maximum magnitude. The frequency will then be the bin number times the bin size, which we computed earlier. Note that we don't actually need to compute the square root to find the maximum magnitude, so our actual code skips that step.<br />
<h2>
More</h2>
We do a bit more in our code, like identify the nearest semi-tone and find the difference between the that semi-tone and the identified frequency, but for stuff like that we'll leave the code to speak for itself.Bjorn Rochehttp://www.blogger.com/profile/17072425815152893296noreply@blogger.com19tag:blogger.com,1999:blog-7225698277211840079.post-60265372187802202812011-12-15T07:29:00.000-08:002011-12-15T07:29:14.353-08:00FCC calls for quieter commercials, but how?<a href="http://perezhilton.com/tag/calm_act/#.TuoQ7Zifu04">In</a> <a href="http://online.wsj.com/article/SB10001424052970203430404577092530932474076.html">the</a> <a href="http://www.cbsnews.com/8301-503544_162-57342486-503544/fcc-passes-rules-banning-extra-loud-commercials/">news</a> recently is the so-called "CALM Act" (<a href="http://en.wikipedia.org/wiki/Commercial_Advertisement_Loudness_Mitigation_Act">Commercial Advertisement Loudness Mitigation Act</a>), which will force TV and cable broadcasters (specifically, multichannel broadcasters) to make advertisements and content be the same volume.<br />
<br />
The problem of blaring commercials, the TV equivalent of the <a href="http://en.wikipedia.org/wiki/Loudness_wars">loudness wars</a>, have been going on for some time, but with newer technologies, including digital broadcasting, it has gotten worse. The fundamental issue is that advertisers want to be heard, so they want to be louder than their competition (the program material). However, it's not just a matter of submitting content with higher volume -- broadcasters, whether analog or digital, have limits to the maximum volume they transmit. Instead, they use recording tricks called compression and limiting to boost the average levels of their recordings while keeping the maximum just within limits. The result is a commercial that sounds louder that the program.<br />
<br />
While digital technology has made it possible to take this loudness to an extreme, digital distribution has also provided one part of the solution: each piece of program material can be pre-marked with loudness information using a standard called <a href="http://www.atsc.org/cms/index.php/standards/recommended-practices/185-a85-techniques-for-establishing-and-maintaining-audio-loudness-for-digital-television">A/85 rp</a> which is used by the consumer's television to determine playback volume.<br />
<br />
The trick is to accurately determine the loudness of the material, so that the A/85 tags can be correctly applied. As it turns out, this is no simple task. The ear is more sensitive to some frequencies than others, and you don't want to use simple averaging because then long periods of silence would allow commercials to get away with short loud segments that were disproportionately loud. To get around these issues, A/85 rp recommends the use of a well researched standard called ITU-R BS.1770 (which may be more familiar from the EBU metering and normalizing standard which uses it, EBU R 128). The ITU standard allows the measurement of loudness that very closely matches human perception of loudness, and offers recommendations for use in live, short and long form content.<br />
<br />
Will the system be gamed? Perhaps content creators will find some way to trick ITU measurement system to make their content appear less loud than it really is, but even if they do, it seems unlikely that they will be able to game the system anywhere near as well as they currently do.<br />
<br />
How will the FCC know if the system is working, and which broadcasters are using the system? They will rely on the public to call-in complaints. Of course, since this has, for years, been the number-one complaint they have received, I don't anticipate too much difficulty there.Bjorn Rochehttp://www.blogger.com/profile/17072425815152893296noreply@blogger.com1tag:blogger.com,1999:blog-7225698277211840079.post-86016802933645421392010-10-26T14:02:00.000-07:002010-10-26T14:02:33.595-07:00Linear Interpolation for Audio in C, C++, Java, etc.Linear Interpolation in digital audio came up recently, so I'm posting it here. I hope it's useful for other folks.<br />
<br />
Technically, Linear interpolation is the act of fitting a line through existing points and computing new data from that line. This might sound complex, but it turns out to be pretty easy, and we can do it with a few lines of code.<br />
<br />
Visually, we can think about drawing a line between two points, and then being able to find the y value for any given x. However, I actually think it's easier to think of it non-graphically because linear interpolation is really just a kind of weighted average.<br />
<br />
For audio, we frequently want to use linear interpolation because it's easy to implement, computationally efficient, and it's "smooth" in some sense that I won't get into, but I will say that it generally does not create clicks and pops when you don't want it to. Linear interpolation is useful for handling fader changes and button-push "de-bouncing" and so on, and it's often great for simple cross-fades and the like.<br />
<br />
The formula for linear interpolation is derived from the formula for the line between two points. You can see <a href="http://en.wikipedia.org/wiki/Linear_interpolation">wikipedia</a> for the details. I am omitting it here and jumping straight to an example. To perform a linear interpolation of 100 samples where y[0] = 7, and y[100] = 20, our code would look something like this:<br />
<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">double start = 7;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">double end = 20;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">for( int i=0; i<100; ++i ) {</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> double ratio = i/100.0;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> y[i] = start * (1-ratio) + end * i;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">}</span><br />
<br />
You can think of <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">ratio</span> as the weight given to the <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">start</span> variable, and <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">1-ratio</span> as the weight given to the <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">end</span> variable. As we slide through the samples, we slowly transition from the start value to the end value.<br />
<br />
Notice I've been very careful to make sure <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">y[0]</span> is actually 7, and <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">y[99]</span> is not quite 20, so that <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">y[100]</span> will smoothly transition to 20 as required. Off-by-one errors can screw this up and while you might not hear the difference, you want to get that right or you could end up with pops, weird overs, or other subtle problems.<br />
<br />
Now you might say that the above code is not very efficient. You can improve on it somewhat using the code below, but be aware that if you interpolating over a large number of samples, especially if you are using single precision floats, you might not quite end up where you expect. The performance gain for this more complex code is likely to be minimal on modern computer hardware, but may be substantial on DSP hardware, where operations like floating point adds take much less time than floating point divides. A clever compiler could theoretically make the same object code out of these two code snippets if it can determine that precision won't be an issue.<br />
<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">double start = 7;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">double end = 20;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">int length = 100;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">double interval = ( end - start ) / length;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">y[0] = start;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">for( int i=1; i<length; )="" ++i=""></length;></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> y[i] = y[i-1] + interval ;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif;">By the time we get to the end, </span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">y[length-1]</span><span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif;"> should be </span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">( end - start ) / length * length = </span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">( end - start ) </span><span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif;">larger than the </span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">start</span><span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif;">, which is exactly right.</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif;">That's all there is to Linear Interpolation, so let's go to an audio example: </span><span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif;">Say we want to go from off, or mutted to on, or unmutted, without a click. Instead of 7 and 20, we'd use 0.0 for off, and 1.0 for on. Also, instead of setting the values in the array, we are going to be multiplying the values in the array, because that's how we do gain changes. Now, let's say we don't know what a good length of time is for unmutting, so lets just make that a variable. Below is a function that takes an array of mono samples, transitions them from off to on at a given time with the given interval. I haven't tested this exact code, but it should be good enough for illustrative purposes:</span><br />
<span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">void unmute( float data[],</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> int totalSamples, //how many samples in our array</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> int startUnmute, //when do we start unmutting?</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> int transitionLength ) //how long is our transition?</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">{</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> //basic sanity check:</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> if( startUnmute + transition > totalSamples )</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> exit( -1 ); //or throw an exception if this were java</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> //process the muted samples:</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> for( int i=0; i<startunmute; )="" ++i=""></startunmute;></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> data[i] = 0; //effectively multiplied by zero</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> //process the transition samples.</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> // this is where the linear interpolation</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> // happens. We are interpolating between 0 and 1,</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> // and multiplying the samples by that value:</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> </span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">for( int i=0; i<transitionlength; )="" ++i="" {=""></transitionlength;></span><br />
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> double ratio = i/(double)transitionLength;</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> data[i+startUnmute] *= ratio; //multiply by the ratio, which is transitioning from 0 to 1</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> }</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> // the rest of the samples don't need to be processed:</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> // they are effectively multiplied by 1 already.</span></div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">}</span>Bjorn Rochehttp://www.blogger.com/profile/17072425815152893296noreply@blogger.com2tag:blogger.com,1999:blog-7225698277211840079.post-23536096786419310112009-12-09T10:59:00.000-08:002010-04-09T08:19:18.636-07:00Linearity and dynamic range in Int->Float->Int<i>Update: </i><a href="http://blog.bjornroche.com/2010/04/comments-on-conversions.html"><i>some comments</i></a><i>.</i><br />
<br />
In my <a href="http://blog.bjornroche.com/2009/12/int-float-int-its-jungle-out-there.html">last blog post</a>, I discussed converting audio from integer to floating point back to integer, mostly from a programming perspective. I showed how there are a lot of ways to do the conversion. Most audio folks would say, "huh, I thought there were only two ways to convert floating point numbers to integers." And they'd be right: with and without dither. So what's all the fuss about?<br />
<br />
Indeed, that's a good question. Most audio folks have this expectation:<br />
<ol><li>When I have dither off and no effects (including volume, etc) I expect to be able to get out exactly what I put in.</li>
<li>When I have dither on, I expect it to sound good.</li>
</ol>Point 1 is what we referred to as bit transparency in the previous post, and we found lots of ways to do that. Point 2 is a bit more subtle. How do you make something sound good? In this case, we mean transparent, and what's especially critical is that we eliminate truncation and IM distortion which are the hallmarks of <a href="http://www.digido.com/more-bits-please.html">cold, harsh digital audio</a>.<br />
<div class="" style="clear: both; float: right; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0.5em; padding-right: 0.5em; padding-top: 0.5em; text-align: left; width: 320px;"><div class="separator" style="clear: both; text-align: center;"><a href="http://3.bp.blogspot.com/_-pZI7Bl38cw/Sx_qDM_VnsI/AAAAAAAAABA/ZYN_DBDChlo/s1600-h/matched-v-unmatched.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/_-pZI7Bl38cw/Sx_qDM_VnsI/AAAAAAAAABA/ZYN_DBDChlo/s320/matched-v-unmatched.png" /></a></div><small>Figure 1. Comparison of 16-bit conversion using the same scaling factor (matched) vs. different scaling factors (mismatched). Mismatched scaling factors come from Method 3 from previous post and matched are Method 2.</small></div><br />
What we need when it comes to transparency and avoiding that cold harsh sound is linearity. In this regard, the methods discussed in my last post, transparent or not, don't stack up equally. You might think you could judge them by inspection, but the mathematics are a bit more complex. Let's be clear about what we need to test: what we <i>don't</i> care about is how accurately a given conversion method responds to a DC signal: we aren't measuring the temperature or the amount of fuel in a tank. Rather, when we talk about linearity in audio we are referring to the ability to accurately translate dynamic information. Think about it: when you buy an analog-to-digital converter, you aren't concerned about its ability to accurately measure a certain input voltage, are you? No, you care about it's frequency response and dynamic range. In the same way, we must ensure maximum signal-to-noise ratio and dynamic range in our conversions. It turns out not all the conversions from my last post have good dynamic performance.<br />
<br />
<span style="font-size: x-large;">Tests</span><br />
<br />
It is sometimes claimed that the percent error introduced by "mismatched" conversion (ie Method 3 from the previous post) is small, and therefore of little concern, but percent error is not what matters in a dynamic system such as audio, so we will not concern ourselves with that and investigate the dynamic performance instead. In Figure 1 we show the results of "mismatched" conversion. In this case we are converting from a source signal of 2 sine waves in double precision to 16-bit integer (to simulate A/D conversion), then to single-precision floating point and back to 16-integer (to simulate a standard editing workflow), and finally back to double precision (to simulate D/A conversion). This is more or less the minimum error we can expect with the mismatched method if we use audio editing software but do not use DSP, and therefore represents a best-case scenario. In the dynamic analysis, it becomes clear that using different scaling factors produces more noise whether dither is used or not. In fact, the difference made by dither is dwarfed by the difference in techniques. Just as importantly, the quality of the noise is bad: rather than shifting the noise floor up, we see spikes indicating that the noise is likely to be audible even at low levels. These results also suggests that it is important to use the same scaling factors throughout the processing chain.<br />
<br />
<div class="" style="clear: both; float: right; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0.5em; padding-right: 0.5em; padding-top: 0.5em; text-align: left; width: 400px;"><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><div class="separator" style="clear: both; text-align: center;"><a href="http://3.bp.blogspot.com/_-pZI7Bl38cw/SxgUOMM4ufI/AAAAAAAAAAw/tH7GqBH7BFw/s1600-h/figure.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/_-pZI7Bl38cw/SxgUOMM4ufI/AAAAAAAAAAw/tH7GqBH7BFw/s400/figure.png" /></a></div><small>Figure 2. Quantization and dithering from float to int and back to float is tested at 16 bits (a,b) and 24 bits (c,d) using a full-scale sine (a,c) and the sum of two sine (b,c). Notes: the sum of two sines does not clip; clipped signal and raw quantized signal are not shown in a.</small></div></div>Figure 2. shows the dynamic performance of conversion using 2^n, (2^n)-1 and "asymmetrical" conversion (ie Method 4 from my previous post). We will discuss below that "asymmetrical" is a misnomer. We also looked at dithered and non-dithered versions.<br />
<br />
Two types of tests were run: first, a full-scale sine wave was generated, converted to int, and back to float for FFT analysis. The second test was the same except that two sines, each at 1/2 full scale were summed together. Each test was run at 16 and 24 bits. Note that the full-scale sine wave cannot be accurately represented in some of these conversion methods, resulting in some clipping.<br />
<br />
As you can see, all dithered converters performed fine at 16-bit as long as nothing was out of scale. At 24-bit, the weakness of the (2^n)-1 converter becomes clear: it actually performs worse than rounding (ie. no dithering). Clearly (2^n)-1 is not an acceptable transformation for 24-bit integers and single precision floating point numbers. The 2^n converter performed admirably on all tests except the 16-bit full-scale test (1a). Those small spikes line up perfectly with the spikes caused by clipping as expected (results not shown) meaning that it is harmonic distortion -- not the worst thing that could happen, but, still, the asymmetric converter does outperform it in this regard.<br />
<br />
As mentioned, I'm calling Method 4 from my previous post the "asymmetric" method, but it is only asymmetric in the sense that you apply different math to positive and negative numbers. As these results show, it <i>is</i> linear. Moreover, it is symmetric with respect to dither amplitude, which is what ensures its linear behavior.<br />
<br />
<span style="font-size: x-large;">Conclusions</span><br />
<br />
Clearly the two winners here are the so-called asymmetric method and the (2^n) method. Both methods excel in the critical areas of bit transparency and linearity. Even their un-dithered performance is quite good, and they are obviously superior to other methods.<br />
<br />
The one area in which the asymmetric model outperforms the (2^n) model is in terms of clipping signals that originated from higher resolution. Even with dither, we still see incorrect behavior with the the (2^n) model because dither only finds its way to 1/2 LSB, whereas +1 clips by going 1 LSB over. The question is whether or not this matters. Indeed <a href="http://lists.apple.com/archives/coreaudio-api/2009/Dec/msg00046.html">there is some debate about the importance of +1</a>. My opinion? +1 is a value that occurs in the real world and it's not always possible for the code that's producing the +1 to know what the output resolution is going to be. For example, a VST synth plugin has no way of knowing what the output resolution is going to be, so it can't be expected to know what to scale its output to. When converting from 24 bit to 16 bit and using float as an intermediary, there is no simple way to solve this problem.<br />
<br />
On the other hand, non-pro A/D converters frequently clip around -.5 dBFS, which is below +1 - 1 LSB anyway. Conceivably, you could also correct for this by introducing a level shift at the output equal to 1/2 LSB, but that's equivalent to turning your converter into a (2^n)-.5 converter -- it solves one problem, but introduces another. All that said, there is no reason not to develop software, especially libraries, drivers and other software intended for use by multiple type of users including audiophiles and pro audio engineers, that is convenient to use while meeting the highest audio standards: just use the asymmetric converters.<br />
<br />
Given the potential hazards found in mixing and matching conversion methods, I recommend that all libraries (and drivers, if possible) offer options for various conversion settings, both to minimize bit transparency problems and unnecessary quantization noise, until all libraries and drivers can standardize on the asymmetric conversion method. This is the only way to guarantee transparency and maximize linearity. As these results show, this issue may be more important than dither.Bjorn Rochehttp://www.blogger.com/profile/17072425815152893296noreply@blogger.com0tag:blogger.com,1999:blog-7225698277211840079.post-30545219449577128342009-12-02T13:51:00.000-08:002009-12-06T20:07:46.486-08:00Int->Float->Int: It's a jungle out there!It turns out that the simple operation of converting from float to integer and back is not so simple. When it comes to audio, this operation should be done with care, and most programmers do, in fact, put a lot of thought into it. The problem most programmers observe is that audio, when stored (or processed) as an integer, is usually stored in what's called "two's complement" notation, which always gives us 1 more negative number than positive. When we process or store floating point numbers, we use a nominal range of -1 to +1.<br />
<br />
The fact that there are more negative numbers than positive numbers has caused some confusion amongst programers, and a number of different conversion methods have been proposed. Here is my survey of how a number of existing software and hardware packages handle this conversion. In these examples, I show conversions for 16-bit integers, but they all extend in the obvious way to other bit depths. It is important to consider how these methods extend to larger integers, especially how they extend to 24-bit integers, so I've tested bit transparency for these methods up to 24-bit using single precision floating point intermediaries, correcting for the fact that IEEE allows for extended precisions to be used in computations. Endianness is irrelevant here, because everything works for big and little endian systems.<br />
<br />
Transparency is only required or possible when the data has not been created synthetically or altered via DSP (including such simple operations as volume changes, mixing, etc). In cases where transparency is not possible, dither must be applied when converting to integer or reducing the resolution. In many software packages it is up to the end-user to make this determination and manually switch dither on or off. In my next post I will discuss dithering and linearity.<br />
<br />
<table border="0" bordercolor="#000000" cellpadding="2" cellspacing="0" class="" style="width: 100%;"><tbody>
<tr><th style="background-color: #104386; color: white; text-align: left;"><br />
</th><th style="background-color: #104386; color: white; text-align: left;" width="25%">Int to Float<br />
</th><th style="background-color: #104386; color: white; text-align: left;" width="25%">Float to Int*<br />
</th><th style="background-color: #104386; color: white; text-align: left;" width="25%">Transparency<br />
</th><th style="background-color: #104386; color: white; text-align: left;" width="25%">Used By<br />
</th></tr>
<tr><td>0)<br />
</td><td width="25%">((integer + .5)/(0x7FFF+.5)<br />
</td><td width="25%">float*(0x7FFF+.5)-.5<br />
</td><td width="25%">Up to at least 24-bit<br />
</td><td width="25%"><span style="font-size: small;">DC DAC Modeled</span><br />
</td></tr>
<tr><td>1)<br />
</td><td width="25%">(integer / 0x8000)<br />
</td><td width="25%">float * 0x8000<br />
</td><td width="25%">Up to at least 24-bit<br />
</td><td width="25%"><span style="font-size: small;">Apple (Core Audio)</span><sup><span style="font-size: small;">1</span></sup><span style="font-size: small;">, ALSA</span><sup><span style="font-size: small;">2</span></sup><span style="font-size: small;">,</span><span style="font-size: small;"> MatLa</span><span style="font-size: small;">b</span><sup><span style="font-size: small;">2</span></sup><span style="font-size: small;">, sndlib</span><sup><span style="font-size: small;">2</span></sup><br />
</td></tr>
<tr><td>2)<br />
</td><td width="25%">(integer / 0x7FFF)<br />
</td><td width="25%">float * 0x7FFF<br />
</td><td width="25%">Up to at least 24-bit<br />
</td><td width="25%"><span style="font-size: small;">Pulse Audio</span><sup><span style="font-size: small;">2</span></sup><br />
</td></tr>
<tr><td>3)<br />
</td><td width="25%">(integer / 0x8000)<br />
</td><td width="25%">float * 0x7FFF<br />
</td><td width="25%">Non-transparent<br />
</td><td width="25%"><span style="font-size: small;">PortAudio</span><sup><span style="font-size: small;">1,</span></sup><sup><span style="font-size: small;">2</span></sup><span style="font-size: small;">, Jack</span><sup><span style="font-size: small;">2</span></sup><span style="font-size: small;">, libsndfile</span><sup><span style="font-size: small;">1,3</span></sup><br />
</td></tr>
<tr><td>4)<br />
</td><td width="25%">(integer>0?integer/0x7FFF:integer/0x8000)<br />
</td><td width="25%">float>0?float*0x7FFF:float*0x8000<br />
</td><td width="25%">Up to at least 24-bit<br />
</td><td width="25%"><span style="font-size: small;">At least one high end DSP and A/D/A manufacturer.</span><sup><span style="font-size: small;">2,4</span></sup><span style="font-size: small;"> XO Wave 1.0.3.</span><br />
</td></tr>
<tr><td>5)<br />
</td><td width="25%">Uknown<br />
</td><td width="25%">float*(0x7FFF+.49999)<br />
</td><td width="25%">Unknown<br />
</td><td width="25%"><span style="font-size: small;">ASIO</span><sup><span style="font-size: small;">2</span></sup><br />
</td></tr>
<tr><td colspan="5" style="background-color: #104386; color: white; text-align: left;" width="100%"><small>*obviously, rounding or dithering may be required here.</small><br />
<span style="font-size: small;"><span style="font-size: 13px;">Note that in the case of IO APIs, drivers are often responsible for conversions. The conversions listed here are provided by the API.</span></span><br />
</td></tr>
</tbody></table><br />
Method 0 is one possible method for preserving the DC accuracy of a DAC, and is included here for reference.<br />
<br />
Edited December 6, 2009: Fixed Method 3. (0x8000 and 0x7FFF were backwards)<br />
<br />
<span style="font-size: x-small;">Sources:</span><br />
<sup><span style="font-size: x-small;">1</span></sup><span style="font-size: x-small;"> Mailing list</span><br />
<sup><span style="font-size: x-small;">2</span></sup><span style="font-size: x-small;"> Perusing the source code (this, of course, is subject to mistakes due to following old, conditional or optional code)</span><br />
<sup><span style="font-size: x-small;">3</span></sup><span style="font-size: x-small;"> libsndfile FAQ goes into detail about this.</span><br />
<sup><span style="font-size: x-small;">4</span></sup><span style="font-size: x-small;"> Personal communication.</span>Bjorn Rochehttp://www.blogger.com/profile/17072425815152893296noreply@blogger.com4tag:blogger.com,1999:blog-7225698277211840079.post-67202494704884617452009-11-11T10:46:00.000-08:002009-11-11T18:53:38.778-08:00WAVE64 vs RF64 vs CAFRight now I am choosing new a default internal audio file format for XO Wave, and I'd like to choose a format that offers large file sizes and high resolution. I'd like to use an existing popular standard rather than inventing my own or using RAW audio. The pro audio industry is finally moving towards 64-bit file formats, and the three options supported by most pro software are<br />
<br />
<ul><li>Wave64, aka Sony Wave64, originally developed by Sonic Foundry before 2003, is an open standard and a true 64-bit format: all 32-bit fields are replaced with 64-bit fields, and all chunks are 8-byte word aligned. Instead of the dreaded FourCC it uses GUID. Other than that, it is pretty much the same as WAV, so the spec is barely 4 pages long, although in my opinion it could stand to be a bit longer, as many aspects of WAV are so poorly devised it really wouldn't hurt for someone to put it all in one place. <a href="http://www.hydrogenaudio.org/forums/lofiversion/index.php/t35550.html%3Cbr%20/t32422-50.html">Some people have criticized</a> the use of GUID on the grounds that there will never be that many chunks, but this misses the point: the point of using GUIDs is that anyone can define their own chunk without having to check with Sony or register a chunk ID. It's actually rather clever.</li>
<li>RF64 was proposed in 2005 by the EBU <a href="http://www.sr.se/utveckling/tu/bwf/prog/RF_64v1_4.pdf">with full knowledge of Wave64</a>. Although the proposal stated basic requirements that could have easily been met by a few minor extensions to Wave64, and they stated a desire to "join forces" with the developers of Wave64, they made no effort to do so other than to say they hoped they'd be involved. Moreover, the same document proposes RF64 as an alternative, incompatible 64-bit extension to the WAV format. Unlike Wave64, RF64 is not a true 64-bit format. All existing "chunks" remain 32-bit, so, for example, markers, regions and loops will no longer work past a certain number of samples. Even EBU's levl chunk will not work with RF64 because it uses a 32-bit address for pointing to the "peak-of-peaks" in the raw data. RF64 offers the much made-of promise of backwards compatibility via a "junk chunk", but, of course, this is possible with Wave64 as well, as pointed out in the Wave64 spec.</li>
<li>CAF, or Core Audio Format was Apple's entry into the ring. Apple didn't want to be left out of the 64-bit game, after all, and around the same time in 2005 they released CAF. Since they are Apple, they figured people would adopt it (Logic would, if no one else), even if there were competing specs. Their approach, however, was to start from scratch, and it's pretty refreshing. Indeed, the spec addresses practical issues to ensure that important features are implemented, and it even makes that tiny little bit of extra effort required to avoid file corruption by not requiring a header rewrite to finalize a recording of unknown length (Anyone who's ever recorded using software knows that once in a while something goes wrong and a file ends up corrupted. It's so nice that someone finally addressed this in a spec.).</li>
</ul>The WAVE format is problematic in many, many ways. For example, in some places it uses zero-based indexing, in others it uses one-based indexing. Sometimes it uses signed integers for raw audio data, other times unsigned. That may not seem so bad, but considering how simple the data it's trying to carry is, but when you add to that the fact that Microsoft had to use format extensions just to clear up ambiguous documentation (and they've still got an ambiguously documented "fact" chunk), it's really not good territory. It is a shame that both Sonic Foundry/Sony and the EBU chose WAVE as the format to extend. Moreover, it's annoying that EBU designed their own, incompatible 64-bit extension to WAVE when a superior one already existed.<br />
<div><br />
</div><div>Some people think the whole "backwards compatibility" thing is a bunch of hooey because it puts an undo burden on the people writing the libraries. Erik de Castro Lopo, author of the popular LGPL'ed libsoundfile says:<br />
</div><div><br />
</div><div><blockquote>Quite honestly, its stuff like this that makes me think the people who write these specs smoke crack!<br />
</blockquote><blockquote>If I were to follow the ... insane advice [about retaining backwards compatibility], the test suite would have to write > 4Gig files in order to write a real RF64 file instead of just a normal WAV file.<br />
</blockquote><blockquote>In order to avoid this insanity, libsndfile, when told to write an RF64 file does exactly as its told.<br />
</blockquote><div>I would add that the backwards compatibility adds another point of failure in the recording process, in the same way that header rewrites are a point of failure in most current formats (except for CAF and "chunkless" formats like RAW and AU).<br />
</div><div><br />
</div><div>All that aside, RF64 is gaining some popularity and support -- probably more than Wave64. As for CAF, it's less popular, but since it's an Apple standard it's probably not going anywhere even if it's not going to be the "next big thing." It could be a fine place to work from, but just scanning the docs everything I looked at brought up a few issues that worried me. For example:<br />
</div><div><br />
<br />
<br />
<ul><li>The CAFMarker data-type has three design flaws I noticed. One is that the frame position is a floating point number. I might be missing something here, but in a format where everything else that counts frames and bytes as 64-bit integers, why are we suddenly using floats? Sure that will be integral to pretty big numbers since it's 64-bit, but it's still a float. I didn't use a format like this to get pretty accurate big numbers when I could get completely accurate big numbers! Internally, most apps are going to be converting 64-bit integers to 64-bit floats, which is insane. Another problem is mChannel, which is the channel (starting at 1) that the marker refers to or zero if the marker refers to all channels. Okay, seems reasonable, except that the spec also defined a channel mapping with a 32-bit channel layout bitmask. Why not use that? Granted you might have more than 32-channels, but that's not going to be the most common case, and you could give your users a choice. Consistency is important in APIs. Also, let's face it, the CAFMarker, if not all the basic chunks, should be versioned and extensible. Sure all that takes a few more bits (well, not the float/integer thing), but it's really nothing compared to the sea of data in most audio files.</li>
<li>In the SMTPE timecode types they define <span style="font-family: Monaco, Courier, Consolas, monospace; font-size: 11px; line-height: 14px; white-space: pre;">kCAF_SMPTE_TimeType30Drop. <span style="font-family: Times; font-size: medium; line-height: normal; white-space: normal;">Now, the fact is that there's really no such thing as 30 Drop, but I can see an argument for including it out of completeness. However, the documentation states that: "<span style="font-family: 'Lucida Grande', Geneva, Helvetica, Arial, sans-serif; font-size: 12px;">30 video frames per second, with video-frame-number counts adjusted to ensure that the timecode matches elapsed clock time.</span>" Which is wrong. If you actually had 30 Drop it would run ahead of elapsed, or "wall-clock" time. "Aha!" you say, "they really mean 29 Drop, which is often just called 30 Drop because <i>everyone</i> knows there's no such thing as 30 Drop." But, I'm afraid you are wrong, because there's another constant for that, <span style="font-family: Monaco, Courier, Consolas, monospace; font-size: 11px;">kCAF_SMPTE_TimeType2997Drop</span>, with pretty much the same documentation, only in this case, it's correct to say that the timecode matches elapsed time. (well, it's very close anyway)</span></span></li>
</ul><div>So CAF might be flawed, but probably no more so than WAVE and anything built on it. The reliability factor is sweet. Really. The fact that many people, especially in broadcast, seem to be wanting RF64 support is a detraction, though.<br />
</div><div><br />
</div>Of course, I might just be over-engineering it. The AU format has been around forever, is super simple and provides high resolution, uncompressed audio of ANY length (it's not even limited to 64-bit). Of course, it lacks metadata which might be useful for BWF-style info as well as region data, but hey, it's wicked simple.<br />
</div><div><br />
<br />
An interesting side note is that by choosing an appropriately sized junk/empty chunk in the header, Wave64, RF64 and CAF can actually be converted from one to another in-place.<br />
</div></div>Bjorn Rochehttp://www.blogger.com/profile/17072425815152893296noreply@blogger.com1tag:blogger.com,1999:blog-7225698277211840079.post-7144475287187553432008-10-23T00:22:00.000-07:002009-11-11T08:27:26.810-08:00Signs that your cat may have a drug or alcohol problem[caption id="attachment_152" align="alignright" width="158" caption="Adorable behavior such as this may be a sign of something more sinister!"]<a href="http://stuff.bjornroche.com/old-blog-uploads/2008/10/photo.jpg"><img class="size-medium wp-image-152 " title="Warning sign of cat alcohol or drug abuse" src="http://stuff.bjornroche.com/old-blog-uploads/2008/10/photo-225x300.jpg" alt="Adorable behavior such as this may be a sign of something more sinister!" width="158" height="210" /></a>[/caption]<br/><br/>If your cat is using alcohol and drugs, it's a good bet they're doing everything possible to keep that activity hidden. The last thing they want is for their owners to give them a "hassle" about his newly-found "entertainment." But continued alcohol and drug use will affect your cat's behavior, attitudes and even choice of friends.<br/><br/>Here are some signs to look for, if you think that your cat may be using:<br/><br/><strong>Mood Swings</strong><br/><ul>Most cats go through normal mood swings. But look for extreme changes -- one minute happy and giddy followed by withdrawal, or fits of clawing at the furniture more than usual. Is your cat both aloof and prone to acting out? These are possible signs of drug and alcohol abuse. </ul><br/><strong>New Friends?</strong> <br/><ul>If you cat is using, chances are they will begin hanging out with other cats with similar interests. Has your cat suddenly turned away from their old friends? Are they hanging out with an older (driving age) group or with those that you suspect are using drugs? </ul><br/><strong>Physical Health</strong> <br/><ul>Have you noticed a change in appetite? Is your cat extremely finicky about the food they eat? Does your your cat have strange or inexplicable sleeping patterns? </ul><br/><strong>"Evidence"</strong><br/><ul>Have you notice anything missing lately? Alcoholic beverages? Maybe some really neat sounding pill bottles? </ul><br/><strong>Attitude</strong> <br/><ul>Has your cat suddenly developed a complete disregard for others? Does your cat get in your way or have a "bad attitude"? Is your cat evasive or troublesome, perhaps hiding when they know they've done something bad?</ul><br/><strong>Little Things</strong> <br/><ul>Have you noticed a change in hairstyle or "fashion" choices? Are they suddenly using breath mints consistently? Is your cat suddenly very secretive? </ul><br/><strong>Overt Signals</strong> <br/><ul>Has anyone ever told you your cat is drinking or using drugs? Do you know that they have "experimented." Have they suddenly developed the need for additional money, for vague or unexplained reasons? Have you ever seen them stagger? Or have you noticed any slurred speech? Changes in the pupils of their eyes, or redness or bloodshot eyes? </ul><br/>Again, many of these changes could be attributed to normal cat behavior. But if you have noticed a pattern of several of these "signals" your cat may be using alcohol or drugs.<br/><br/> <br/><br/>thanks to <a href="http://alcoholism.about.com" target="_blank">alcoholism.about.com</a> for.... virtually all of this text.Bjorn Rochehttp://www.blogger.com/profile/17072425815152893296noreply@blogger.com3tag:blogger.com,1999:blog-7225698277211840079.post-68721451990049476412008-10-03T06:42:00.000-07:002009-11-11T08:27:26.813-08:00My Wikipedia Entry for Gossip GirlWhile everyone else is obsessed with the idea of teens getting it on (OMG! Teenagers having Sex! Can it be?) I couldn't help but notice something else about the show based on a school affiliated my own <a href="http://www.ivygateblog.com/2007/11/according-to-the-wsj-collegiate-school-is-best-ivy-feeder/">snotty-a#$@ed</a> childhood alma-matter, so I wrote my own wiki entry...<br/><h3>Gossip Girl (TV Series)</h3><br/><div style="width: 240px; float: right; border: 1px solid #666; font-size: 80%; text-align: center; margin: 5px; padding: 5px;"><img title="Jessica Szohr. In the eugenically sterilized world of Gossip Girls, black people have been improved: their new eye color is blue!" src="http://stuff.bjornroche.com/old-blog-uploads/2008/08/220px-jessica_szohr_lf.JPG" alt="Jessica Szohr. In the eugenically sterilized world of Gossip Girls, black people have been improved: their new eye color is blue!" />In addition to lots of hot white characters, Gossip Girl also features a hot non-white character who plays Dan's BFF. (She even looks less white in other pictures!) If you believe she grew up in a scary part of Brooklyn, I'll sell you a bridge to that borough.</div><br/>Gossip Girl is an American television teen drama based on the popular novel series of the same name written by Cecily von Ziegesar. Gossip Girl revolves around the lives of socialite young adults growing up on New York's least exciting neighborhood, the Upper East Side. The characters attend elite academic institutions while dealing with sex, drugs, jealousy, and other issues faced by today's rich white kids (oh, right, and Dan's BFF, what's-her-name<sup>1</sup>. She has to deal with pretending not to fit in, despite being from scary Brooklyn). Issues not addressed in detail include: depression, college admission, school work, money, medical problems, emotional problems, etc. (fortunately, that TV unfriendly stuff doesn't happen to these kids, even, surprisingly, anorexia).<br/><br/>Despite the appearance of <del>non-wasp characters</del> a non-wasp character, the audience is able to fantasize themselves into an all-white world (just like <a href="http://en.wikipedia.org/wiki/Groton_School">Groton</a>'s founder <a href="http://en.wikipedia.org/wiki/Endicott_Peabody_(educator)">Endicott Peabody</a> dreamed of, too!) because that character at least has blue eyes and is really hot and has a <a href="http://thetvaddict.com/2008/04/28/we-gossip-with-gossip-girl-star-jessica-szohr/">"normal"</a> job working in a cafe (off-camera she's a model).<br/><br/>Apparently, the writers attended New York City private schools either in 1947, or in the South, because several of the episodes depict things like coming out cotillions (I know the characters are too old for bar/bat mitzvahs, but cotillions? WTF? How about the <a href="http://query.nytimes.com/gst/fullpage.html?res=9B0DE0D9163DF931A15751C1A961948260">Gold and Silver Ball</a> next season?).<sup>2</sup><br/><br/>Anyway relax, this show is totally race-sanitized: no major Asian characters or Black characters (unless they have blue eyes, exotic sounding names and can pass for children of characters from the '90's hit show <a href="http://en.wikipedia.org/wiki/Aisha_Tyler">Friends</a>), and definitely no Jews. Not the Upper East Side I remember from my high school days, but it's definitely the Upper East Side many of my friends' parents probably dreamed about. It's sort of like a eugenics project, only it's not real, so you can feel good about that, too, because some of those schools really are eugenics projects and that's more than a little creepy.<br/><h4>Criticism</h4><br/>The show's critics allege that the show raises some adult themes. What exactly constitutes an adult theme? According to <a href="http://en.wikipedia.org/wiki/Calvin_and_Hobbes">Bill Waterson</a>, it's things like doing paperwork, filing, etc. Indeed, the show has that: Nate becomes involved in the family business and so on, so I advise parents caution when allowing their children to watch this show.<br/><h4>Season 2</h4><br/>Rumor has it that more adult themes are in store next season. Perhaps they'll be doing taxes, or learning right from wrong or even drinking <a href="http://en.wikipedia.org/wiki/Sex_and_the_City">adult drinks</a> like cosmos? Perhaps the smarter ones will grow up properly and turn into <a title="Hot Intellectual Chicks" href="http://hotintellectualchicks.com" target="_blank">chicktellectuals</a>.<br/><h4>Discussion Questions</h4><br/><ul><br/> <li>Wasn't there an Asian chick with no lines in the pilot?</li><br/> <li>What's more boring, a blog about a TV show or a TV show about a blog?</li><br/> <li>If you were going to have a bitchy argument synchronized to a song, which song would it be?</li><br/> <li>In what way is Jessica Szohr's character not white?<sup>3</sup></li><br/></ul><br/><h4>Notes</h4><br/><sup>1</sup> It's hard to remember the character's name when <a href="http://en.wikipedia.org/wiki/Gossip_girl_episodes">she's missing from more episodes than any other character</a>. I wonder why that is.<br/><sup>2</sup> Okay, truth be told, there were a few cotillions, but nobody got excited about them except the young ladies' mothers.<br/><sup>3</sup> We're looking for either everyone talks about how great she is in order to feel accepting of her, or she provides advice and, you might say, spiritual guidance the <del>real</del> other characters.Bjorn Rochehttp://www.blogger.com/profile/17072425815152893296noreply@blogger.com2tag:blogger.com,1999:blog-7225698277211840079.post-73348671052378952262008-03-24T01:35:00.000-07:002009-11-11T08:27:26.846-08:00Input Lists (Corrections)In <a href="http://blog.bjornroche.com/?p=111">Part II</a> of my series on Stage Plot input lists I got a few of my facts wrong. Not about input lists, but about the band I picked on, <a href="http://www.kcfunk.com/">Kansas City Funk Syndicate</a>. It wasn't because David Freeland, who had originally contacted me with some excellent questions about his band's input, was unclear, it was just that so much time had passed between asking his questions and me actually blogging about them. I forgot some important facts and got confused, so here are some clarifications.<br/><br/>One thing I wrote was that Funk Syndicate should buy a new mixer. This would have been good advice had my version of reality been the right one. David clarified that their mixer <em>can</em> reorder inputs -- the reason their input list seemed "out of order" was because of "ergonomics on the [mixer] and the money channels since some of our preamps are better than others at the moment. A lot of the channel moving is all of the relabeling more that the capabilities of the mixer." In short, they could have changed the channel order but it takes time to relabel their mixer and their outboard gear. (I am also guessing that by ergonomics they mean that they wanted the important stuff on one "page" of their mixer, which only has 16 physical faders, but at least 32 physical inputs). Makes perfect sense.<br/><br/>Still, it presents a problem for the FoH mixer who isn't used to finding most vocals at one end of the mix and one lonely vocal at the other. Confound that with something that I am guessing happened: Funk Syndicate sent their stage plot and Input List to the venue explained everything, including their unusual input list, the venue said it would be no problem, but failed to communicate it to the mix engineer in advance and the mix engineer got caught by surprise but Funk Syndicate thought he knew what the deal was going to be. I'm just guessing, but that kind of thing happens all the time.<br/><br/>I don't have a great solution to the issue without actually seeing the whole rig, and knowing all the concerns, but here's what I suggested to David:<br/><br/><blockquote><br/>If it were me, the first thing I would consider would be simplifying the rig -- sometimes less is more. Personally, I have never heard the difference between high quality and very high quality preamps in a live situation, but you guys might be hearing it -- especially with in-ears, or if the preamps are actually full channel strips or you've got other outboard. Or just give in and lose a little of that on your money channels. Labeling can also be an issue. You could try two colors of sharpie (one for each setup).<br/></blockquote><br/><br/>I don't know if this is workable -- every band is different and sometimes it can be difficult, emotionally, to have spent a hard-earned cash on high-end gear and not use it because it doesn't fit ergonomically into the rig. Something else to consider might be to give your venue two input list options, and let them choose. This could backfire because you are giving them choices they are not used to, so you'd have to find a concise way to explain the difference. You'd also want to be able to switch between them easily, preferably on site because the odds of the venue actually passing the question on to the FoH engineer and getting back to you with his or her answer is small.<br/><br/><center> * * * </center><br/><br/>Well, David has a tricky situation, no doubt, and I'm not sure I've done much to solve the problem because there is no easy answer. If you find yourself in a similar situation, remember to be as communicative, open and clear as you can be and remember to anticipate problems and be ready for them. A weird input list is one potential problem, so if you have a good reason for not following the usual rules, make sure to communicate those reasons, and, if you can, have a <a href="http://www.xowave.com/tees">backup plan</a>!Bjorn Rochehttp://www.blogger.com/profile/17072425815152893296noreply@blogger.com0tag:blogger.com,1999:blog-7225698277211840079.post-68208031501191891112008-03-17T02:01:00.000-07:002009-11-11T08:27:26.849-08:00Input Lists (The Other Part of Your Stage Plot) Part II<img align="right" src="http://stuff.bjornroche.com/old-blog-uploads/2007/12/lolsounds2.jpg" width="200" height="110" title="A good input lists helps the stage cats patch you in right!"/>In <a href="http://blog.bjornroche.com/?p=105">part I</a> of this post, I covered the basics of input lists. I noted in that article that most people don't need to worry too much about the actual numbers they assign to their inputs in their input lists (aka the channel numbers), because most engineers won't pay them much attention. I recently got an email from David Freeland of the Kansas City <a href="http://www.kcfunk.com">Funk Syndicate</a> who had a question about the channel numbers on his input lists, and I'll address that in this posting, but many readers may simply want to read part I, since channel numbers are not relevant to most bands.<br/><br/><em>NOTE: while this post still stands on it's own, it turns out I got some facts wrong about KC Funk Syndicate. For corrections, see <a href="http://blog.bjornroche.com/?p=114">Input Lists (Corrections)</a></em><br/><br/><h2>Why your channel numbers generally don't matter</h2><br/><br/>In general, you might think it would be easy for a mix engineer to adhere to your request for channel numbers. In reality, different mixer configurations and the desire to have continuity between sets (especially at <a href="http://blog.bjornroche.com/?p=7">festivals</a>) makes this difficult. For example, a typical small format mixer looks like this:<br/><br/><center><br/><img id="image107" src="http://stuff.bjornroche.com/old-blog-uploads/2008/02/1642vlz3-lrg.jpg" alt="16 channel mixer" /><br/></center><br/><br/>but most large format live consoles don't look like that, because there are too many channels and you want the important stuff (the mains and the busses) in the middle where you have the best access to them. So, large format live consoles look like this:<br/><br/><center><br/><img id="image108" src="http://stuff.bjornroche.com/old-blog-uploads/2008/02/gl2800_lrg.jpg" alt="Large format live console" /><br/></center><br/><br/>The upshot is that building from left to right (which is how you setup your input list) is <em>not</em> the only, obvious way to go. On the big mixer pictured above, for example, I might put my lead instruments and auxes on the first 24 channels (which are to the left of the main section), and the drums, bass, and other rhythm instruments on the next 24 channels, which are on channels 25-48, which wouldn't make any sense at all except to someone who was looking at the same mixer. Another way to go might be to alternate bands on the left and right sides of the mixer, which might seem strange, but I heard of one festival which had a rotating stage, and they might want to do that to swap out bands faster -- especially if they had two engineers sharing the same console!<br/><br/>Don't even think about trying to organize your input list in anticipation of this, though, because you won't know where the split on the mixer occurs, how your engineer likes to split things up, or what the other acts will be. Even if you did, your input list would cease to be a logically grouped, organized reminder of the important sound sources of your band, which is the whole point of the input list.<br/><br/><h2>KC Funk Syndicate's Stage Plot</h2><br/><br/>Let's, take a look at KC Funk Syndicate's Stage Plot (Contact Info is Blacked out):<br/><br/><table><br/><tr><br/><td rowspan="2"><img id="image106" src="http://stuff.bjornroche.com/old-blog-uploads/2008/02/kcfunkstageplot.thumbnail.png" alt="KCFunkStagePlot" /></td><br/><td><a href="http://stuff.bjornroche.com/old-blog-uploads/2008/02/kcfunkstageplot.png">Open in this window</a></td><br/></tr><br/><tr><br/><td><a target="_blank" href="http://stuff.bjornroche.com/old-blog-uploads/2008/02/kcfunkstageplot.png">Open in new window</a></td><br/></tr><br/></table><br/><br/>The first thing you'll notice, aside from the fact that they've got a very large band, with a very well organized stage plot is that their input list is out of order. Their vocalists are at the top (good!), except for one, Karl, who is close to the bottom (bad!). There's also some channels that are not strictly inputs, but rather talkback channels and so on (confusing!).<br/><br/>I asked David about this and he explained that they really wanted the channel numbers assigned to the numbers he gave them because they were supplying their own monitor system and engineer, and the venue (a large casino) was supplying FoH system and engineer. Now, I'm sure the FoH engineer asked, as I did, why the channel order had to be that way. Couldn't the monitor engineer use a more sensible channel order? Apparently, the answer is no, because the monitor engineer was using a pre-programmed digital mixer who's tracks could not be reordered. That stray vocalist had been added to their act recently, and so had to be added to the end because the digital mixer was incapable of reordering their the tracks into a more sane order!<br/><br/>I don't know how much of the venue's irritation stemmed from not being able to call the shots (FoH engineers usually call the shots on things like channel numbers), and how much stemmed from actual confusion about having the vocals being separate, but David told me the venue was definitely upset.<br/><br/>Given this limitation, David did the right thing presenting an input list with the channel numbers assigned in order, and he was able to communicate the situation very clearly to me, so I presume he did so with the venue as well. That said, I agree with the venue, that David should consider other options in the future.<br/><br/><h2>What's the Solution?</h2><br/><br/>Since David upset the venue, he did some research, came across some of my previous posts on stage plots and asked for my advice. Before I get to that, I should say that if Funk Syndicate were the only band on the bill, and the FoH engineer was advised of the situation in advance and they had plenty of setup time, the FoH engineer should have been able to deal with the unusual setup. It's not ideal, but it's hardly an impossible situation and it's all clearly documented. Oddities like this are life sometimes, and David is clearly open to suggestions. I don't know if the FoH engineer was being a jerk or simply making a recommendation that they change their setup -- all David said was that the venue, "gave him some grief." I hope it was the latter.<br/><br/>Clearly, the ideal situation for Funk Syndicate would be to ditch the mixer that can't cope with changing channels. Seriously, I <a href="http://www.xowave.com">love digital gear</a>, but it has to suit your purpose, and in this case, the centerpiece of a <em>live</em> setup is so inflexible that it can't be made to play well with other gear, so it should be dumped. I realize it was a big investment, and Funk Syndicate may not need to go to this extreme for what is, in fact, little more than a nuisance, but it <em>is</em> the <em>right</em> solution. E-bay will help recoup the loss. Although this is the best solution, keep in mind that even with a mixer that can swap channels you might still run into trouble -- what if FoH (for whatever reason) needs to rout you into channels 48-56 and your mixer only has 36 channels. In this (admittedly very unusual) case, you will not get your channels to line up.<br/><br/>Short of that, I do recommend reprogramming the mixer so that the input list is more in keeping with what FoH engineers are used to. Since Funk Syndicate are probably usually the only act on the bill, probably have plenty of prep time, and do a long set (I am guessing here) many of the usual "don't tie yourself down to one set of channels" argument won't apply, but I think they will continue to rub FoH engineers the wrong way if they continue with their current setup. I would definitely recommend, at the very least, reprogramming their board so that they could use the following input list (or something like it). Notice that I've left 2 channels open so they've got some room to grow. Maybe they should leave even more channels open depending on their mixer and snake configuration, but this way they are not expecting their venue to have more than 24 channels.<br/><br/><table><br/><tr><th>chan</th><th>Input</th><th>Notes</th></tr><br/><tr><td>24</td><td>Frank Vox</td><td></td></td><br/><tr><td>23</td><td>Neil Vox</td><td></td></td><br/><tr><td>22</td><td>Kim Vox</td><td>Wireless</td></td><br/><tr><td>21</td><td>Kevin Vox</td><td></td></td><br/><tr><td>20</td><td>David Vox</td><td></td></td><br/><tr><td>19</td><td>Bob Vox</td><td></td></td><br/><tr><td>18</td><td>Karl Vox</td><td>Wireless</td></td><br/><tr><td>17</td><td>Open</td><td></td></td><br/><tr><td>16</td><td>Trumpet</td><td>Wireless</td></td><br/><tr><td>15</td><td>Sax</td><td>Wireless</td></td><br/><tr><td>13-14</td><td>EWI</td><td>Stereo</td></td><br/><tr><td>12</td><td>Guitar</td><td></td></td><br/><tr><td>10-11</td><td>Keys</td><td>Stereo DI</td></td><br/><tr><td>9</td><td>Open</td><td></td></td><br/><tr><td>8</td><td>Bass</td><td>DI</td></td><br/><tr><td>7</td><td>Overhead</td><td>Single</td></td><br/><tr><td>4-6</td><td>Toms</td><td>3</td></td><br/><tr><td>3</td><td>Hi Hat</td><td></td></td><br/><tr><td>2</td><td>Snare</td><td></td></td><br/><tr><td>1</td><td>Kick</td><td></td></td><br/><tr><td>(1-2)</td><td>(FoH)</td><td>Return</td></td><br/><tr><td>(3)</td><td>(Stage Talkback)</td><td>Return</td></td><br/></table><br/><br/>Note that I've left returns on there, so that the venues know they are needed, but I've separated them from the rest of the mix. If they wanted to use them as inputs to to monitors I would recommend patching them in as auxes, or as much higher channels (not otherwise assigned), rather than assigned channels, because the FoH guy won't want to see his own outputs coming in as input channels.<br/><br/>Again, if Funk Syndicate is in a situation where FoH can't conform, then this won't solve their problems, but it should do in well over 90% of cases and it should keep most FoH engineers pretty happy.<br/><br/>A final solution is to do nothing and simply be extremely humble when facing FoH engineers. This will leave David facing some irritation, frequent, though slight delays in setup (since things are not where people are used to seeing them) and maybe occasional minor mistakes, but probably never anything worse than that.<br/><br/>So, while there's no perfect solution, there are plenty of workable options. David will have to be aware of the compromises -- irritating FoH mixers a bit vs reprogramming his mixer vs suffering with mismatched channels in his monitor and FoH mixes vs dropping a lot of cash on a new mixer. Even with a new mixer, there may be a rare case of channel mismatch, so nothing is perfect in this world.Bjorn Rochehttp://www.blogger.com/profile/17072425815152893296noreply@blogger.com1tag:blogger.com,1999:blog-7225698277211840079.post-51601029042258654812008-02-21T01:18:00.000-08:002009-11-11T08:27:26.853-08:00Input Lists (The Other Part of Your Stage Plot) Part I<img align="right" src="http://stuff.bjornroche.com/old-blog-uploads/2007/12/lolsounds2.jpg" width="200" height="110" title="A good input lists helps the stage cats patch you in right!"/>Previously I've posted a lot about stageplots. You'd think I'd've said it all, but the truth is I've glossed over something important: the input list. I recently got an email from David Freeland of the Kansas City <a href="http://www.kcfunk.com">Funk Syndicate</a> who had a question about input lists. I'll get to his question in part II, and, today, focus on the basic facts of input lists, which are really quite simple.<br/><br/><hr />Previous articles on Stageplots:<br/><ul><br/> <li><a href="http://blog.bjornroche.com/?p=7">What you need to know about playing a festival</a>, which alluded to stageplots.</li><br/> <li><a href="http://blog.bjornroche.com/?p=6">Stage plots and Input Lists (Updated 9/21/06!): what they are, why you need one, and how to make one</a></li><br/> <li><a href="http://blog.bjornroche.com/?p=70">Creating Stageplots on your Mac with OmniGraffle</a></li><br/></ul><br/><hr /><br/><br/>You might be tempted to think input lists are not that important. After all, if you're a huge touring act, you're probably touring with your own engineers who know your inputs, and if you're five-piece local act, house engineers might not even bother looking at your stage plots much less your input lists most nights. The truth is that unless you are a solo acoustic act it's very unlikely that any engineer is going to keep a complete input list in their heads and having it written down is the way to go. If you are ever asked for an input list, that means someone is trying to help you, so you should try and give them the best input list you can, so they can help you as best they can. Making good input list is ridiculously easy, and, as David's experience has taught him, having a good input list can save you some grief (actually, there wasn't much wrong with David's input list, and it still caused him some grief!). So let's just take a few seconds right now to get this right!<br/><br/><h2>We've got a stage plot, why an input list?</h2><br/><br/>Your stage plot clearly shows all your instruments, and should show how you want them connected to the sound system (via DI or mike -- you did do that, right?), so why do you also need an input list? There are a few reasons. The most common reason is simply a check list of all instruments so that the engineers can make sure they've got signal for everything. It can also be a place for additional notes or reminders. This is especially true if you've got a huge act and you simply can't put all the information you need on your stage plot. It's also a good chance to put the important stuff up top to help your engineers focus on what's import -- eg. lead vocals first! Since most mix engineers build their mix from the "bottom up" you might want to number your list backwards, like so, but we'll see in a moment why that probably doesn't matter:<br/><br/><table><br/><tr><th>chan</th><th>input</th><th>notes</th></tr><br/><tr><td>7</td><td>Vocals</td><td>Wireless Mike (We can provide)</td><tr><br/><tr><td>6</td><td>Acoustic Guitar</td><td>DI</td><tr><br/><tr><td>5</td><td>Bass</td><td>DI</td><tr><br/><tr><td>3-4</td><td>Drum Overhead</td><td></td><tr><br/><tr><td>2</td><td>Snare</td><td></td><tr><br/><tr><td>1</td><td>Kick</td><td></td><tr><br/></table><br/><br/>Notice how the input list is ordered in the same way that the mixer might be set up -- so that the mix can be built from the "bottom up", and the "money channel" lead vocals, are at the top, where they are least likely to be missed. Notice, also, that stereo sources get two channels -- you'll do the same thing with stereo keyboards and so on.<br/><br/>For most acts, that's all there is to it. Really. You are done. It's that easy and it will make your show go that much more smoothly.<br/><br/>But, you say, what if, say, another act goes on first and uses channels 5 and 6 for toms, but is otherwise the same? What if the house mixer has inputs 1-16 reserved for some other purpose, like a multitrack feed? What if the the mixer is some weird configuration or the mix engineer like to put the vocals on the low number channels? What does the house engineer do? The answer is, they ignore your channel numbers. Completely. And that's okay, because most of the time you're channel numbers don't matter, and unless your channel really do numbers matter for some reason, you can stop reading.<br/><br/>If you think your channel numbers really do matter, part II is coming up.Bjorn Rochehttp://www.blogger.com/profile/17072425815152893296noreply@blogger.com1tag:blogger.com,1999:blog-7225698277211840079.post-19397196356876330322007-12-16T22:53:00.000-08:002009-11-11T08:27:26.877-08:00Creating Stageplots on your Mac with OmniGraffleA while back I posted about <a href="http://blog.bjornroche.com/?p=6">stage plots</a> and why they are so important, especially at <a href="http://blog.bjornroche.com/?p=7">festival gigs</a>, but I did not go into much detail about how to make one, other than to say draw one by hand if you lack the technical skills. Of course, there's as many ways to make them as there are people making them, but I've been using a program called <a href="http://www.omnigroup.com/applications/omnigraffle/">OmniGraffle</a> for a while, and it occurred to me that it would be a great tool for making stage plots if you're a mac user. It's extremely intuitive once you spend fifteen minutes with it and if you've got the right stencils, it's a breeze.<br/><br/>First download and install <a href="http://www.omnigroup.com/applications/omnigraffle/">OmniGraffle</a>. You won't need to buy it to try it out. You may not even need to buy it at all if your stage plots are simple, since it lets you add up to 20 objects before you have to pay. After you've downloaded Omnigraffle and tried it out a bit, <a href="http://stuff.bjornroche.com/old-blog-uploads/2007/11/stage-plots.zip">download my stencils</a>, which include an amp stencil, an instrument stencil, and an general purpose stage plot stencil.<br/><br/>After downloading it, unzip the file, and copy the stencils into ~/Library/Application Support/OmniGraffle/Stencils/. Next time you start OmniGraffle, it will see the new stencils and you can grab the images and lay them out on a document. When you're done, save the document and use the export feature to save as a jpeg, or pdf. I threw some instruments together and came up with this in no time flat:<br/><br/><center><br/><a href="http://stuff.bjornroche.com/old-blog-uploads/2007/11/sample-stage-plot.pdf"><br/><img src="http://stuff.bjornroche.com/old-blog-uploads/2007/11/sample-stage-plot.jpg" alt="OmniGraffle Stage Plot" width="75%" height="75%" /><br />(click image to enlarge)<br /></a></center><br/><br/>Beautiful it a'int, but clear it is, especially considering all the stuff on stage. For details on what should <strong>really</strong> go into your stage plot, remember to see my <a href="http://blog.bjornroche.com/?p=6">blog posting on that subject,</a> but you get the idea. If you have an instrument not covered (I only did the basics), you can either use a box and label it or find a picture of it online.Bjorn Rochehttp://www.blogger.com/profile/17072425815152893296noreply@blogger.com7tag:blogger.com,1999:blog-7225698277211840079.post-40744489310221550162006-10-09T20:31:00.000-07:002009-11-11T08:27:26.946-08:00What you need to know about playing a festivalI love stage managing festivals. But a lot of bands, even ones who have been playing in clubs for years, don't know how to prepare for festival shows, which are very different from regular nightclub gigs. With the <a target="_blank" href="http://candlerparkfallfest.org">Candler Park Fall Fest</a> coming up, I thought it would be good to write an article on the subject of preparing to play for a festival.<br/><br/><h3>Got stage plot?</h3><br/><br/>I've already talked about the importance of stage plots, especially at festivals in a <a href="http://blog.bjornroche.com/?p=6">previous posting</a>. The gist is this: stage plots help a lot so you should have one. <em>Note: If your looking for some software to make a stageplot, I've added an entry about using something called omnigraffle <a href="http://blog.bjornroche.com/?p=70"> to make stageplots on your mac</a>.</em><br/><br/><h3>The Schedule</h3><br/><br/>Staying on schedule is the job of the stage manager, but it's your job to work with them to do so. If you are late, or take time getting setup on stage, or the stage manager expects trouble getting you off stage, or there was a problem earlier and the stage manager needs to makeup time, your set may be cut short. It may or may not be fair, but it's always important to get off the stage when asked. I have never had to force a band offstage, but I'm sorry to admit that I have had to ask them to cut their sets a bit short on a few occasions. This was usually because they arrived late, or without a stage plot (or both!), but it does happen that I accidentally gave one band too much time, and had to cut a little time from another band. If this happens to you, it sucks. It really sucks. But it happens, and it's good to be prepared. For example, if you've got a song or two you want to finnish with, it's a good idea to keep track of time yourself (or ask for updates while on stage) so that you can skip a less important song.<br/><br/>If you feel that you behaved professionally and the stage manager cut your set short unfairly, especially by more than five or ten minutes, bring it up with them another time after the show or tell the booking agent or event director. You might not get preferential treatment next time, or extra money, or even an apology, if the stage manager/event planner thinks they made the right decision, but at least they'll know how you feel and it will help them to do a better job next time.<br/><br/><h3>Forget the sound check</h3><br/><br/>Most festivals try to cram as much music in as possible. This, combined with other considerations (like neighborhood noise laws), typically means there's no time for sound checks, so it's important to do what you can to help your sound crew prepare. Most sound crews can do a fine job even without a sound check, and, as you play, they'll tweak things very quickly so that you'll be sounding great long before your first song is over. However, it's always good to check in with them before you go on so they know what to expect and can set things up for you from the get-go. The most important thing you can do is provide a stage plot, but talking to them and describing your sound and what's most important to you about your sound helps a great deal.<br/><br/><h3>Meet your monitor mixer</h3><br/><br/>The sound on stage can be quite good at a festival, especially outdoors, where the lack of walls and ceiling may help reduce feedback. But remember how you didn't get to do a sound check? That means it may not sound perfect on stage from the first song. At a well run festival with a large stage, you'll typically have separate engineers for FoH (Front of House, which is what the audience hears) and monitors (which is what you hear). Make sure to introduce yourself to your monitor engineer before the show, and tell them what each musician needs to hear onstage. Typically, they can guess some things, like that the vocalists need to hear themselves, but it's good to check in with them either way. If you get onstage and you're not hearing what you need to hear, alert the monitor mixer or stage manager. Most systems allow the monitor mixer to listen to what is going through each monitor speaker without having to go onstage to listen, but they might not know a problem exists on a certain monitor speaker without you telling them. Alerting them to the trouble really can make a difference (just be sure to tell them nicely, since the monitor mixer is your bands best friend while you're on stage).<br/><br/>As with performing in a venue, the sound onstage can vary drastically from the house sound. That's nothing to worry about but it may be disorienting. Many singers have a hard time hearing their vocals with little to no reverb, for example, but reverb can cause feedback problems, and the monitor mixer usually has fewer effects at his or her disposal, so it's best to do without if at all possible.<br/><br/><h3>Share equipment</h3><br/><br/>Many bands, especially those with younger members, are adamant about using their own equipment, even if the festival provides equipment for them. This is understandable, especially if the band has a very particular sound that requires special equipment. However consider this:<br/><br/><ul><br/><li>It is usually harder to get equipment in and out of a festival setting. Festivals often take place in settings that were not designed with large equipment in mind.</li><br/><li>Any time you spend getting your equipment on or off stage is time taken away from your set. (especially if I'm stage managing the event)</li><br/></ul><br/><br/>Finally, I'll let you in a on a little secret: outdoor sound reenforcement sucks. Yes, you heard it here first: doing outdoor sound is hard. Doing a good job without a soud-check or an engineer who has heard your band before is hard. Setting up your equipment correctly while the previous band is striking and doing it all in 15 or 20 minutes (10 minutes on my stage) is hard. Even with the right equipment, the end result can be mediocre compared to virtually any indoor setting, and very often the right equipment is not available. So be sure to ask yourself this simple question: do you really want to spend all that time getting the "perfect sound" that no one's going to hear anyway, or do you want to have time to play an extra song or two?<br/><br/>I don't mean to say that there's never a good reason to use your own equipment, just that you may have to make a choice between hauling gear, and playing more songs. The choice is yours and for many bands getting the right sound is both legitimate and necessary. Just be sure not to make a decision that cuts into your set time unless you have to.<br/><br/><h3>Expect the Unexpected</h3><br/><br/>Things usually go well if everyone is prepared. Sometimes things go well even if someone is not prepared. But in a festival, it's not uncommon for things to go wrong. With much of the work being done by volunteers, and without the common luxuries of sound-checks and familiar stages and equipment, someone is bound to be caught off-guard at some point. With all the adrenalin and exhaustion of everyone there, it's easy to get in a tizzy about this and make more mistakes (maybe I could write another entry just about that), so it's especially important to remember that everyone is there to have fun, and most people, especially the audience, are quite forgiving.<br/><br/>With the right preparation, though, serious problems are almost always avoidable, so do your homework (make a stageplot!) and then relax and break a leg!Bjorn Rochehttp://www.blogger.com/profile/17072425815152893296noreply@blogger.com3tag:blogger.com,1999:blog-7225698277211840079.post-54577373354997321112006-09-14T00:54:00.000-07:002009-11-11T08:27:26.950-08:00Stage plots and Input Lists (Updated 9/21/06!): what they are, why you
need one, and how to make one<em>Note: If your looking for some software to make a stageplot, I've added an entry about using something called omnigraffle <a href="http://blog.bjornroche.com/?p=70"> to make stageplots on your mac</a>.</em><br/><br/>Occasionally, I get have the time to work on a music event. It doesn't happen often, but when it does, I have the pleasure of working with bands and helping them do a great show. For the past three years, now, I've been stage manager for the <a href="http://www.candlerparkfallfest.org">Candler Park Fall Fest</a>, and it's a great experience. A lot of other festivals are not well run -- bands just show up at the specified time and try to make due with what's there. They're often lucky if there's more than one sound engineer. This can be a frustrating experience for everyone but especially for the bands, so when I work on an event I try to do everything I can to run the stage as professionally as possible, but it also takes a little cooperation from bands.<br/><br/>In order to make a festival run well, a lot of things need to come together, and one of the most important parts of that is getting accurate stage plots and input lists for all the bands. Most professional bands have a stage plot as part of their contract rider. Even if they do their own stage setup and have lots of time to sound-check, a stage plot helps ensure in advance that the necessary equipment will be provided. When it comes to doing festivals, though, many luxuries, such as sound-checks, and a nice long break between acts, simply aren't there, and the stage plot helps ensure that things go smoothly, because, with a stage plot, <em>everybody</em> knows exactly what needs to be done.<br/><br/>I do all my advance planning around the stage plots, making sure that the required equipment is available and that any tricky band transitions are worked out in advance. When the festival starts, I plan the whole day around my stage-plots, and I use them to coordinate with the bands, the stage crew, and both the monitor and FoH (Front of House) positions to ensure that everything is setup, miked and amplified properly and that every band is ready to go on as quickly as possible. Towards the end of each set, I go over the next act's stage plot again, so I can give instructions to the stage crew and prepare for the transitions. If there is anything tricky or unusual, I usually oversee it myself during the transition. With a good stage plot, I can give instructions and help the bands and crew setup.<br/><br/>Without a stage plot we have to figure it out as we go along. With a stage plot, I can accurately assess how long each transition will be, and time the sets so that each band can play as long as possible without getting off schedule. Without a stage plot, I have to assume that it's going to take a long time, so everyone gets shorter sets. (I am a real stickler for the schedule because if you go off schedule, someone ends up at the short end of the stick.)<br/><br/>You don't get more time in your set because it took you a long time to setup, so providing a stage plot and input list means you get a longer set. Last year's Fall Fest had bands that were prepared play for about 50 minutes, while unprepared bands were forced to cut their sets down to as short as a half hour. It makes that much difference.<br/><br/><h1>How to Make a Stage Plot</h1><br/><br/>One thing I've learned, is that many bands don't have a stage-plot or input list, an many don't even know what they are. That's fine if you're just playing the local pub. It's even fine if your playing big venues an have lots of prep time. It's not fine if your playing a festival.<br/><br/>Fortunately, making a stage plot is easy. All you need to do is draw a birds-eye view of the stage with everything important, such as musician locations, mikes and DI boxes. Mike stands should be labeled boom or straight. Mike types should be specified if they are non-standard. Monitor locations and any other on-stage requirements should be specified. Top it off with your band name, date and contact info and you're done. Don't try and get too fancy or show off your art skills, that only makes it harder to read. Remember this is not promotional material -- it's technical information.<br/><br/>Put your band name and contact info at the top. It's also good to date the plots so that you can ensure that everyone has the current one. Below that is the actual diagram. Most stage plots have the band facing down so the audience is at the bottom of the page. I prefer this view as it puts down-stage down and up-stage up and house left on the left and house-right on the right, but the upside-down version of this is acceptable, too. Here are some examples of good stage plots, some of which include input lists, which we'll get to in a minute:<br/><br/><ul><br/><li><a href="http://stuff.bjornroche.com/old-blog-uploads/2006/09/ht-stage-plot-05.jpg">Johnny Knox and Hi-Test have an almost perfect stage plot</a>. I've blacked out the contact info, but otherwise, this is their plot. Everything that's important to them is here -- locations of equipment, types of stands, even info such as reverb settings are here. Unusual things, such as no DI on the Bass, are clearly marked. There are 2 minor problems: 1. it should have a date, so everyone knows this is the current stage plot, and 2. the stage plot is upside-down from my preferred orientation. Still, this is a great stage plot, and can easily be used to get them on stage and sounding great fast and with minimal hassle.</a><br/><li><a href="http://www.papagrowsfunk.com/production/stageplot.html">Papa Grows Funk</a> have a great stage plot. It clearly shows everything a stage manager and stage crew need to know, including power and specific mike requirements. It's probably overkill for a festival, where 9 mikes probably can't be provided for the drums, but that doesn't matter because the critical info is there.</li><br/><li><a href="http://www.rhythm-city.com/gifjpg/rcstageplot.pdf">Rhythm City's Stage plot</a> is decent, though it could stand to have a key to assure the person looking at it that the box with a circle in it is a monitor amp. It would also be nice if the stage plot indicated clearly weather each stand was straight or boom -- as is the stage crew would probably assume straight unless it says otherwise, or they might assume a boom stand is okay, which it might not be. It would also be great to have musician's names and numbers corresponding to numbers in the key, below, so there was no confusion. Finally, a band can request as many 57s and 58s as they like, but they should not expect to get 4 beta 58s, as this band does.</li><br/></ul><br/><br/>If you don't have software or software skills to make a stage plot on the computer, there is nothing wrong with doing it by hand and scanning or photocopying it. Just make sure to write clearly and legibly. Remember this is not promotional material, so just stick to the facts, and keep it simple and clear.<br/><br/><h1>Stage Plot File Formats</h1><br/><br/>Whatever program you use to make your stage plots, from photoshop, to Microsoft Word or power point, or even boutique software such as <a href="http://www.omnigroup.com/applications/omnigraffle/">Omnigraffle</a>, it's important to send it in a format that can be read by the stage manager. I have Office for Mac, but it doesn't always read e-mailed PC word files correctly. In fact, you shouldn't count on your end user having Office or any other program. Instead, send it in a format specifically designed to be portable and easy to read. You can send a PDF, JPEG, GIF, PNG or anything else commonly used on the web. If all else fails, print it out and mail it.<br/><br/><h1>Input Lists</h1><br/><br/>An input list simply lists every mike, DI Box, synth rack or other sound source on your stage, whether you are providing it or the sound company is providing it. You want to say what the instrument is, and how sound is to get from the instrument to the mixers. For example, a solo guitarist/singer might provide an input list like this:<br/><br/><table><br/><tr><th>Channel</th><th>Instrument</th><th>Input Method</th><th>Notes</th><br/><tr><td>1</td><td>Male Vocals</td><td>Mike (SM 58 or equiv.)</td><td>Very dynamic, but good mike technique. Please use just a touch of reverb. Stereo small hall preferred.</td><br/><tr><td>2-3</td><td>Guitar</td><td>DI</td><td>I have two effects pedals. Stereo out. Please add no additional effects except compression and EQ as needed. Should be bright but not overpower the vocals.</td><br/></table><br/><br/>If it's a long list, it's good to group them in the way that a mix engineer is most likely to group them. For example, you might start with drums, percussion and bass, and move up to rhythm guitar, keys, lead guitar, and then vocals. Better yet, do it in the reverse order so drums and rhythm are at the bottom and lead instruments like the voice are at the top. It's a good idea to highlight or mark the important things: the notes sections in the table above is probably overkill in this department, but it doesn't hurt.<br/><br/>If your band has a great lead guitarist or the vocals really are your band's "money channel", say so on the input list. That way, the mix engineer knows to pay special attention to those instruments. Most professional mix engineers do read this stuff, so if something is important, write it down!<br/><br/><h2>Other stuff</h2><br/><br/>Finally, if your really want to sound your best, there are a few other things you can provide your stage manager with:<br/><br/><ul><br/><li><strong>A Set List:</strong> I may not know the songs, but if you make notes about solos, false endings, and song dynamics, the mix engineer will be prepared and be able to make you sound that much better. I rarely receive these, but when I do, I tend to get more compliments on the sound, so I know it makes a real difference.</li><br/><li><strong>Description of Monitor Mixes:</strong> We know the lead vocalist needs to hear themselves as loud as possible, so we don't need to know that, but if you need something unusual, like extra keyboards in the drum monitor, it's a good idea to have that written down somewhere.</li><br/><li><strong>Photos:</strong> It's great to have pictures of all your band members so no one asks them to leave if they are found hanging out backstage. You should ask your band members to introduce themselves to the stage managers and monitor mixer as soon as they arrive. That's also a good time to discuss any last minute changes or go over your requirements.</li><br/></ul><br/><br/><h1>Break a Leg!</h1><br/><br/>That's it. With this information you are now armed and ready to play at my festivals and probably anybody else's. If you are not asked well in advance for this information, or your get a blank stare when you provide it, it probably means you can expect trouble when it comes time to perform, so be prepared. Now, go break a leg!Bjorn Rochehttp://www.blogger.com/profile/17072425815152893296noreply@blogger.com5tag:blogger.com,1999:blog-7225698277211840079.post-25373287951358938642006-09-14T00:23:00.000-07:002009-11-11T08:27:26.953-08:00Johnny Knox and High Test Stage PlotBjorn Rochehttp://www.blogger.com/profile/17072425815152893296noreply@blogger.com0