Programmers work with signals all the time. We may not normally think of the data we're working with as signals, but treating it that way and learning some basic ways of processing those signals can come in quite handy. Last week I went over the basic signal types that are commonly used in digital signal processing. Today, I'll cover the basic ways we can change a signal using a set of transforms.
These transforms can be used in a variety of ways to accomplish different goals when processing signals, and we'll look at a few use cases as we go through the transforms. We'll need an example signal to apply these transforms to, and I can think of no better signal to use than the workhorse of DSP—the sine wave. The basic equation for a sine wave is
f(t) = sin(t)
Where t is the variable of time, marching forever forward. This basic equation will get embellished with other parameters as we explore the different transforms. We'll start off with the simplest of the transforms.
Musings on software development, technology, and their interconnections with a programmer's everyday life
Search This Blog
Everyday DSP for Programmers: Basic Signals
Digital Signal Processing (DSP) is a field that can be incredibly
useful to almost any programmer. When you think about DSP, you probably
think of complex computational tasks for audio filtering, image
processing, or video editing, but DSP is much more general than that.
The name 'DSP' aptly describes what it is. It has to do with the digital domain, which is directly applicable to any kind of programming. It deals with signals, which includes much more than the normal audio and video signals we normally think about as signals. Any series of data points that changes over time is a signal. That means a stock's price history is a signal, your kid's height over time is a signal, and the number of users on a website is a signal. Signals are all around us, and we deal with them every day. Finally, DSP involves processing those signals in some way to either transform the signal into something more useful for a given purpose or extract desirable information from the signal. Encoding that processing in a fast, automated program is a natural fit for what a programmer does.
The name 'DSP' aptly describes what it is. It has to do with the digital domain, which is directly applicable to any kind of programming. It deals with signals, which includes much more than the normal audio and video signals we normally think about as signals. Any series of data points that changes over time is a signal. That means a stock's price history is a signal, your kid's height over time is a signal, and the number of users on a website is a signal. Signals are all around us, and we deal with them every day. Finally, DSP involves processing those signals in some way to either transform the signal into something more useful for a given purpose or extract desirable information from the signal. Encoding that processing in a fast, automated program is a natural fit for what a programmer does.
A Barely Adequate Guide to JavaScript Canvas
Whenever I want to add a new feature to this blog, I write a post describing the process of researching and implementing that feature first. I've done two Barely Adequate Guides so far, one on syntax highlighting with JavaScript and one on JavaScript charts. The goal with these guides is twofold. First, I get to document what I'm learning about how to implement these features for future reference. Second, it shows at least one way of researching, choosing, and working with a new software library starting from square one.
Nearly everything we do as programmers has already been done before. Maybe not exactly in the same way as we're trying to do it this time, but pretty much every component that makes up any given project already exists in some form out on the Internet already, probably in more than one library. That means we have a choice as to how to spend our time. We can either write that component from scratch and know exactly how it works, or we can find a library and integrate it into our project. Each method has its benefits and costs, and I normally will spend at least a small amount of time looking for a ready-made solution. If I can find one quickly, it's robust, and it has a decent API, I can save a lot of time by programming at a higher level than I would otherwise.
For this Barely Adequate Guide, I want to learn about the HTML5 canvas and start using a JavaScript library that makes using the canvas even easier. I'm planning some articles that will make good use of animated drawings, and it should prove useful for future posts as well. I start, as I always do, with a Google search:
I start with the basic "javascript canvas" search terms to see what comes up. (By the way, I just had a great experience getting this screen cap. I switched from Windows to Linux about half a year ago, and this is the first time I did a SHIFT-PrintScreen. The cursor turned into a cross-hairs and I selected an area to capture. Then a dialog box appeared where I could name the file and choose where to save it. This is a way better experience than having to muck around with Paint on Windows. Linux: 1, Windows: 0.) Here are the top ten results:
I skip past the other HTML5 links and take a look at the Fabric.js library. This looks promising. The Fabric.js library appears to have a lot of features, good documentation, and active support on Github. I take note and look at the next link. It's actually a chapter out of a free online book called Eloquent JavaScript. It looks quite good, but not what I need right now so I bookmark it and keep searching. With the tenth link, I've reached the end of the first page of search results, learned a bit about the canvas, and found one higher-level library.
I could continue paging through the results, but I think I'll have better luck refining my search.
That's right. I want the best. I figure by using the 'best' search term, I'll get at least a few links that will rank or review different JavaScript libraries. I wasn't disappointed:
The second link leads me to a comparison table of JavaScript canvas libraries in a Google doc. It looks a little out of date and doesn't have too many different comparison points, but it's still useful to browse through. I find Pixi.js, EaselJS, and Fabric.js at the top of the list again, along with Paper.js. Both Paper.js and Fabric.js appear to be much larger than the other two libraries, although Fabric.js is more modular so it's potentially comparable to the smaller libraries if I only use the core of it.
I follow the links to each library's website, and I find that they all have demos, example code, and documentation ranging from good to great in quality. With the short time that I spend on each site, I feel that Paper.js and EaselJS have a bit more complicated API, while the Pixi.js and Fabric.js APIs look immediately familiar. Then I visit each of the GitHub repositories to get a sense of how active and popular the libraries were. They all seem to be well maintained with regular and recent checkins and good notes in the readme files for getting started. Pixi.js has by far the most watchers, stars, forks, and contributors, with the other three libraries having similar stats to each other for the most part.
Between its potential ease of use, small size, and popularity, I decide to go with Pixi.js. I wouldn't normally go with the crowd so quickly when choosing a library, but in this context it's a reasonable course of action. If this decision was for a more complex project that depended on a drawing library for its success, I would do a more in-depth analysis and probably experiment with all of the top contenders, but for using a library with this blog, any of these libraries would likely be more than adequate. I want something I can learn quickly, and I want to waste as little time as possible deciding which library to use so I can start learning the library sooner. Clear code examples and popularity are a decent first-order proxy for a detailed evaluation in this case.
The first thing I need to do to start playing with Pixi.js in my blog is to load the JavaScript library. I can either load the source file from https://cdn.rawgit.com/GoodBoyDigital/pixi.js/dev/bin/pixi.min.js or clone the git repo from https://github.com/pixijs/pixi.js, host the pixi.min.js myself, and load it from that location.
One easy way to host JavaScript files is to set up GitHub Pages with this tutorial, make a javascript folder to dump in any JavaScript files you want, and push them up to GitHub. Then you can source the files from your own <username>.github.io URL. I chose to load the source from the main GitHub project, so I added this line within the <header> tag of my Blogger template:
Not too bad, but a bit rudimentary. Let's try something a bit more interesting. How about an oscillating sine wave. For this drawing, I'll have to add animation, but that shouldn't be too hard because animation support is already there by default in the animate function. The hardest part is constructing the sine wave from line segments. Here's the code:
Mesmerizing. That's not bad for a few hours of experimentation and a couple dozen lines of code. Now I can add animated graphics to my posts, and I learned a new trick to add to my repertoire. Pixi.js is a pretty deep library, and you can do a ton of different things with it. It would probably take months to become proficient with it, but getting a handle on it in a few hours was worth the time. If you're in need of graphics or animation for your website, it's a good place to start.
Nearly everything we do as programmers has already been done before. Maybe not exactly in the same way as we're trying to do it this time, but pretty much every component that makes up any given project already exists in some form out on the Internet already, probably in more than one library. That means we have a choice as to how to spend our time. We can either write that component from scratch and know exactly how it works, or we can find a library and integrate it into our project. Each method has its benefits and costs, and I normally will spend at least a small amount of time looking for a ready-made solution. If I can find one quickly, it's robust, and it has a decent API, I can save a lot of time by programming at a higher level than I would otherwise.
An Initial Search
For this Barely Adequate Guide, I want to learn about the HTML5 canvas and start using a JavaScript library that makes using the canvas even easier. I'm planning some articles that will make good use of animated drawings, and it should prove useful for future posts as well. I start, as I always do, with a Google search:
I start with the basic "javascript canvas" search terms to see what comes up. (By the way, I just had a great experience getting this screen cap. I switched from Windows to Linux about half a year ago, and this is the first time I did a SHIFT-PrintScreen. The cursor turned into a cross-hairs and I selected an area to capture. Then a dialog box appeared where I could name the file and choose where to save it. This is a way better experience than having to muck around with Paint on Windows. Linux: 1, Windows: 0.) Here are the top ten results:
- Canvas tutorial - Web API Interfaces | MDN
- HTML5 Canvas - W3Schools
- HTML Canvas Reference - W3Schools
- HTML Canvas - W3Schools
- HTML Canvas Coordinates - W3Schools
- Canvas - Dive Into HTML5
- HTML5 Canvas Element Tutorial - HTML5 Canvas Tutorials
- Fabric.js Javascript Canvas Library
- Drawing on Canvas :: Eloquent JavaScript
- Canvas element - Wikipedia, the free encyclopedia
I skip past the other HTML5 links and take a look at the Fabric.js library. This looks promising. The Fabric.js library appears to have a lot of features, good documentation, and active support on Github. I take note and look at the next link. It's actually a chapter out of a free online book called Eloquent JavaScript. It looks quite good, but not what I need right now so I bookmark it and keep searching. With the tenth link, I've reached the end of the first page of search results, learned a bit about the canvas, and found one higher-level library.
Refining the Search
I could continue paging through the results, but I think I'll have better luck refining my search.
That's right. I want the best. I figure by using the 'best' search term, I'll get at least a few links that will rank or review different JavaScript libraries. I wasn't disappointed:
- My Favorite 5 JavaScript Canvas Libraries • Crunchify
- html5 - Current State of Javascript Canvas Libraries? - Stack Overflow
- powerful javascript canvas libraries - Stack Overflow
- EaselJS | A JavaScript library that makes working with the ...
- What are the best JavaScript drawing libraries? - Slant
- 10 Cool JavaScript Drawing and Canvas Libraries - SitePoint
- Fabric.js Javascript Canvas Library
- Chart.js | Open source HTML5 Charts for your website
- Brief Overview of HTML5 Canvas Libraries - JSter Javascript ...
- Pixi.js - 2D webGL renderer with canvas fallback
The second link leads me to a comparison table of JavaScript canvas libraries in a Google doc. It looks a little out of date and doesn't have too many different comparison points, but it's still useful to browse through. I find Pixi.js, EaselJS, and Fabric.js at the top of the list again, along with Paper.js. Both Paper.js and Fabric.js appear to be much larger than the other two libraries, although Fabric.js is more modular so it's potentially comparable to the smaller libraries if I only use the core of it.
I follow the links to each library's website, and I find that they all have demos, example code, and documentation ranging from good to great in quality. With the short time that I spend on each site, I feel that Paper.js and EaselJS have a bit more complicated API, while the Pixi.js and Fabric.js APIs look immediately familiar. Then I visit each of the GitHub repositories to get a sense of how active and popular the libraries were. They all seem to be well maintained with regular and recent checkins and good notes in the readme files for getting started. Pixi.js has by far the most watchers, stars, forks, and contributors, with the other three libraries having similar stats to each other for the most part.
Between its potential ease of use, small size, and popularity, I decide to go with Pixi.js. I wouldn't normally go with the crowd so quickly when choosing a library, but in this context it's a reasonable course of action. If this decision was for a more complex project that depended on a drawing library for its success, I would do a more in-depth analysis and probably experiment with all of the top contenders, but for using a library with this blog, any of these libraries would likely be more than adequate. I want something I can learn quickly, and I want to waste as little time as possible deciding which library to use so I can start learning the library sooner. Clear code examples and popularity are a decent first-order proxy for a detailed evaluation in this case.
Experimenting with Pixi.js
The first thing I need to do to start playing with Pixi.js in my blog is to load the JavaScript library. I can either load the source file from https://cdn.rawgit.com/GoodBoyDigital/pixi.js/dev/bin/pixi.min.js or clone the git repo from https://github.com/pixijs/pixi.js, host the pixi.min.js myself, and load it from that location.
One easy way to host JavaScript files is to set up GitHub Pages with this tutorial, make a javascript folder to dump in any JavaScript files you want, and push them up to GitHub. Then you can source the files from your own <username>.github.io URL. I chose to load the source from the main GitHub project, so I added this line within the <header> tag of my Blogger template:
<script src='https://cdn.rawgit.com/GoodBoyDigital/pixi.js/dev/bin/pixi.min.js' type='text/javascript'/>
With the library loaded, I can start experimenting with drawing shapes on a canvas. Let's start with drawing a simple line. On the examples page on GitHub there's a Graphics example with sample code. Pulling out the necessary setup code and the code to draw a single line gives me the following first attempt:<div id="canvas-line" style="width: 550px; height: 400px">
</div>
<script type='text/javascript'>
var canvas = $('#canvas-line');
var renderer = PIXI.autoDetectRenderer(canvas.width(),
canvas.height(),
{ antialias: true });
canvas.append(renderer.view);
var stage = new PIXI.Container();
var graphics = new PIXI.Graphics();
graphics.lineStyle(10, 0xffd900, 1);
graphics.moveTo(50,50);
graphics.lineTo(500, 300);
stage.addChild(graphics);
animate();
function animate() {
renderer.render(stage);
}
</script>
The code starts out by defining a <div> with an id that I can refer to in the JavaScript code. Then the JavaScript finds the element with that id, creates a renderer and a canvas, creates a stage for adding graphics contexts, and creates the first graphics context. The graphics context is what's used to draw things, in this case a line. The line style is defined for the context and then the line is defined with a starting point and an end point. Finally, the context is added to the stage and the animate() function is called to render the drawing. The result looks like this:Not too bad, but a bit rudimentary. Let's try something a bit more interesting. How about an oscillating sine wave. For this drawing, I'll have to add animation, but that shouldn't be too hard because animation support is already there by default in the animate function. The hardest part is constructing the sine wave from line segments. Here's the code:
var canvas = $('#canvas-sinewave');
var renderer = PIXI.autoDetectRenderer(canvas.width(),
canvas.height(),
{ antialias: true });
canvas.append(renderer.view);
var stage = new PIXI.Container();
var sinewave = new PIXI.Graphics();
stage.addChild(sinewave);
sinewave.position.x = 75;
sinewave.position.y = 200;
var count = 0;
animate();
function animate() {
count += 0.1;
sinewave.clear();
sinewave.lineStyle(4, 0xff0000, 1);
var amplitude = Math.sin(count) * 100;
sinewave.moveTo(0, 0);
for (var i = 0.1; i < 6.3; i+=0.1) {
var x = i*63.5;
var y = amplitude*Math.sin(i);
sinewave.lineTo(x, y);
sinewave.moveTo(x, y);
}
renderer.render(stage);
requestAnimationFrame( animate );
}
In this case I create a graphics context for the sine wave outside of the animate function and set its origin to where I want the sine wave to start. Then in the animate function, I increment a counter that determines what the amplitude of the sine wave is for the current frame and draw out the sine wave with line segments. Finally, I have to request an animation frame to advance the animation. The result looks like this:Mesmerizing. That's not bad for a few hours of experimentation and a couple dozen lines of code. Now I can add animated graphics to my posts, and I learned a new trick to add to my repertoire. Pixi.js is a pretty deep library, and you can do a ton of different things with it. It would probably take months to become proficient with it, but getting a handle on it in a few hours was worth the time. If you're in need of graphics or animation for your website, it's a good place to start.
How to Determine if Something is Good
I recently came across an old article entitled How Art Can Be Good by Paul Graham that I had tagged as something of interest, and I decided to read through it again. In it he argues that art can be good in an objective sense, and that good art is not simply a matter of good taste. I found this article fascinating because while I agreed with his premise that art can be objectively judged, I disagreed with most of Graham's arguments. With most of his articles, he exhibits clear, sound reasoning, and I learn a great deal from his writing. This article is peculiar in that the reasoning seemed much weaker and more vague, but it still made me think deeply about what makes a thing good so I want to explore that idea more carefully.
Keep in mind that Graham's article was written in December of 2006. He may no longer hold the same beliefs that he did when he wrote this article, and I'm not trying to tear down his ideas about good art or attack him in any way. I respect him both as a writer and as a thought leader in the tech startup community. I'm merely attempting to analyze the reasoning in the article and describe my own thoughts on the subject.
Being able to determine if something is good has much practical value, especially if you're the one creating the thing that you hope is good. When creating a work of art, or any other product for that matter, you want to have a keen sense of what makes it good because the better a product is, the more value it will have for more people. I'm going to widen the net well beyond art at this point because the qualities that make art good can apply to almost anything, so we'll be comparing art to music, movies, video games, literature, food, consumer products, Mathematics, and, of course, software.
You Keep Using That Word…
Right from the outset, Graham entangles the idea of good art with good taste in order to disprove that they are equivalent:
One problem with saying there's no such thing as good taste is that it also means there's no such thing as good art. If there were good art, then people who liked it would have better taste than people who didn't. So if you discard taste, you also have to discard the idea of art being good, and artists being good at making it.He later concludes this argument by saying that if there is no way to make art better, then the Sistine Chapel is as good as a blank canvas, and since that's absurd, we have a contradiction. Therefore good art exists. I agree with the conclusion, but the argument is either circular, a straw man, or a slippery slope. I can't decide which one it is.
First, taste is a characteristic of the person who is judging the art, not a characteristic of the art itself, so they are already two different things. It's easy to think of something that I consider to be good, but I personally don't like it. Take music for example. There is plenty of music, whole genres in fact, that I don't like to listen to, but I can still appreciate that songs from those genres take great skill to perform and that plenty of other people like those songs. I also have guilty pleasures that I know aren't that good in a musicality sense, but I enjoy them all the same. Does that mean I have good taste for some music but not other music? No, it means I have varied tastes in music, and my tastes are different than other people's.
Second, good and better are also different things, yet he uses them as if the person with better taste automatically determines what is good taste. The world is not so narrow and simple. Faulkner and Hemingway are both considered good writers (an understatement, I know), but if one person liked both of their works and another person only liked Faulkner, would the person who liked them both have better taste? There are literary experts that like Faulkner's stream of consciousness style and hate Hemingway's terse, matter-of-fact style and plenty of other experts that love Hemingway's writing and hate Faulkner's. They can still agree that both are great authors and are important to read. Neither literary expert is better than the other because of which author they prefer, and the authors are difficult to rank because they are so different from each other.
Finally, each step of this argument doesn't immediately follow the previous step, and I think it is because the definition of good is vague and indeterminable. In the context of art, the word good can have at least two distinct meanings that I've only alluded to so far. Art can be good in the sense that it takes great skill to create, and it can be good in the sense that it evokes strong emotions in the viewers. Art created with great skill can include new techniques that have never been used before. There are numerous examples of famous paintings that were some of the first to use perspective effectively. At the time the technique was discovered, perspective was a difficult skill to master, and the paintings that showed good use of perspective were ground-breaking. Today a painting can't be considered good purely on its use of perspective.
We can see the distinction between these two concepts of good in different kinds of movies. Certain movies break ground with special effects. The Matrix is a great movie partly because so many incredible special effects were invented for it, and they were put to good use telling the story of the movie. On the other hand, I think Mr. Magorium's Wonder Emporium is a great movie partly because of the strong reactions of joy and sadness I get while watching it. I can jump into that movie at any time during the last third of it, and I'll be choked up within minutes.
Good has multiple distinct meanings, and throughout Graham's article the word seems to shift between these two meanings of requiring great skill and evoking strong emotions. It is generally easier to objectively analyze whether or not something requires great skill than it is to analyze that it evokes strong emotions, but they both play a part in making something good. Good can have other meanings as well, in the sense of morality for example, but Graham didn't get into those and I won't, either.
Know Your Audience
After the introduction, Graham goes on an extended discussion of what type of audience we're talking about when someone says that a piece of art is good. Who is the art good for? Who would appreciate the work of art? After touching on a number of characteristics that would appeal to people generally, noting that art can appeal to different groups of people in different ways, and even bringing aliens into the discussion, he settles on all human beings as the intended audience when art is described as good.
I generally agree with his reasoning here, although it is a bit drawn out and the bit about aliens seemed unnecessary. He did overlook an important group of people, though—experts in the field. He was arguably talking about how to judge whether a work of art is good for a general audience, but expert opinion is still important because experts in a field will have a much different perspective on something in their field than the general populace would. Once you have a certain level of knowledge about a given subject, your ideas about what is important, what is difficult, and what is elegant will change dramatically.
In mathematics, proofs that are particularly elegant can be considered beautiful. This is something that the average person will likely not appreciate, but an expert mathematician will see beauty where anyone else would see incomprehensible jargon. Sometimes the beauty comes from structuring a proof in a way that neatly solves the theorem in a more concise way than was thought possible. Other times the beauty comes from building up intricate mathematical machinery, and just when you think things are going to get even more complex, everything falls into place and the solution practically drops out of the proof's structure quite unexpectedly. These are forms of beauty that take intense study and specific knowledge to appreciate.
Experts will also see depth in something that the average person will fail to notice. A good example of this phenomenon happens in video games. Some games have layers of depth in game play that is not at all obvious on a single play-through. Devil May Cry is an old action game from 2001 where you are a half-demon named Dante who fights demons with a sword and guns. At first glance it's a run-of-the-mill action game, but if you spend enough time with it, you'll discover all kinds of expert-level secrets in the game. The enemies and levels are designed so that it's possible to complete every level without ever taking a hit, and the game keeps track of that, giving you bonuses and special rankings for good performance. The holy grail is a perfect SS game where you never take a hit for the entire game and complete each level within its time limit. To achieve this feat, you need to learn special tricks for using your weapons and defeating enemies. The game has a ton of depth that only experts will see and appreciate. Most of the games that are considered the best by expert gamers are like this, and the opinions of the expert audience are important when determining whether a game is good or not.
Comparing Apples and Oranges
Graham moves on to a discussion of how the general public leans in its preferences for art, and how those preferences stem from errors of personal bias and artist's tricks. He claims that good art can't be determined by a vote the way a good apple or a good beach could because the public is easily swayed by branding and advertising. I disagree both with the claim that voting is ineffective in determining if something is good and that apples and beaches are all that different than art.
Regarding voting, it's true that you may not think something is good while the majority of people think it is good, but it's likely that the set of things that come to the top in a vote includes some pretty good stuff. (Let's ignore politicians here because no one's going to agree that that statement holds for them.) Take smart phones as an easy example. People vote for smart phones with their wallet, and the top 10 list of best selling smart phones is dominated by Apple, Samsung and Xiaomi. You may not like iPhones. You may not like Galaxy phones. But it's pretty likely that you'll find a good phone on that list. They all have good performance, good build quality, and good design.
I find voting to be a pretty good guide for finding all kinds of good stuff. It's how I choose books to read on Amazon. I will nearly always pass on a book that gets less than a four-star rating because in my experience, they've been almost universally bad. I have a much better chance getting a good book with a four- or five-star rating, even though the occasional stinker still makes it through. It takes a strong recommendation from someone I trust to convince me to read a three-star rated book, and a rating less than that is out of the question. Life's too short, ya know?
Regarding apples, it seems entirely possible that I would not like an apple that the majority of people vote as being exceptionally good. What if I like sour apples and most people like sweet apples? What if I like my apples tart, covered in cinnamon, and baked in a pie? What if I hate apples? The point is that there are enough kinds of apples in the world that deciding which ones are good isn't all that different than deciding which works of art are good. Reasonable people are going to disagree on what is good art and what is a good apple. It kind of comes down to what tastes good to you, and now we've come full circle.
I Said I'd Talk About Software
All of these ideas about what makes good art or movies or smart phones also applies to software. The definition of good changes slightly because the user of a piece of software likely doesn't care if it took a lot of skill to make nor will it evoke strong emotions of joy or sadness. Maybe it will cause intense frustration, but that shouldn't be a goal. What good software does do is make the user feel highly skilled. It gives the user a great sense of accomplishment because she can do things easily that were difficult or impossible before. It should also be enjoyable to use and help the user feel productive. These things will make the user happy.
Expert users will find elegance and depth in good software. I am continually impressed by the cleanness of features in Firefox and the limitless capabilities of Vim, although I wouldn't say I'm an expert in either, yet. The point is that good software has layers of depth that keep enticing advanced users to explore further and discover new powers to make themselves more awesome. In the end good software, like good art, is still a matter of taste. Some people will like Chrome instead of Firefox. Some people will like Emacs or Sublime instead of Vim. For something to be good, it has to meet the requirements of being high quality and being appealing to an audience, and beyond that people's preferences are going to come down to taste.
So coming back to Graham's article, I think there are ways to determine objectively if art is good, but once those objective criteria are met, we are still left with a wide variety of art. Then it comes down to personal preferences, and different people are going to like different things. Ideally, good art is determined by both objective criteria and taste, and on that we seem to agree.
Subscribe to:
Posts (Atom)