Saturday, 14 May 2011

Flash Dynamic Sound Generation 2: Musical Notes




Today I learnt how to produce musical notes in the equal temperament tuning using Flash dynamically generated sound. If you would like to see how I dynamically generated the sounds, you can check my previous post here.


Essentially, music notes are just certain frequencies, so I could reuse the different wave-forms I did previously to produce them. Now all I had to do was to find out how to determine the frequencies of the notes. The formula to produce the notes was:


Frequency = 2 ^ (n/12) * 440;
where n is the number of semitones relative to the note A4 which is 440 Hz.


For e.g. for the note A#4, n is 1, therefore the frequency is 2^(1/12) * 440 = 466.16 Hz. If you're not familiar with the note names, it is basically the note (A#) followed by the octave number (4).


Actually, the formula is quite intuitive if we think about it. There are 12 semitones in an octave and each octave is double the frequency of the previous octave. Using this information, we can tell that if we want to double in frequency we need to multiply by a factor of 2. However, we only double every 12 semitones and that is why we need to divide the semitone number by 12. Finally, there is a reference frequency which we need to use and the standard frequency to reference is the note A4 at 440 Hz.


As shown, calculating musical note frequencies is pretty easy and now I'll show how to convert the semitone number into a note name. I.e. Given the n = 2, let's find out how to get the note name "B4". Here's my code with the explanation below:


function NoteNumberToName(noteNum:int):String
{
// number from -69 to 58
// assumes noteNum 0 is A4

// octave number is counted from C, so we have to add an offset
// noteNum 0 is octave 4
var octaveNum:int = Math.floor((noteNum + 9) / 12) + 4;
var octaveNumStr:String = octaveNum.toString();

var octaveNote:int = (noteNum+69) % 12;

var returnString:String;
switch(octaveNote)
{
case 0: returnString = "C"+octaveNumStr; break;
case 1: returnString = "C#"+octaveNumStr; break;
case 2: returnString = "D"+octaveNumStr; break;
case 3: returnString = "D#"+octaveNumStr; break;
case 4: returnString = "E"+octaveNumStr; break;
case 5: returnString = "F"+octaveNumStr; break;
case 6: returnString = "F#"+octaveNumStr; break;
case 7: returnString = "G"+octaveNumStr; break;
case 8: returnString = "G#"+octaveNumStr; break;
case 9: returnString = "A"+octaveNumStr; break;
case 10: returnString = "A#"+octaveNumStr; break;
case 11: returnString = "B"+octaveNumStr; break;
default: returnString = "invalid"; break;
}
return returnString;
}


First of all, the range of notes I'm using is the same as the range of notes available in the MIDI system i.e. 128 notes from C-1 to G9, see here. I'm also taking in the input as a number relative A4 so note A4 is 0, C-1 is -69 and G9 is 58. However, you may wish to change this to a zero-based index if you like.


The quirky thing about note names is that it starts with C while the reference frequency starts from A4, so we have to add an offset of 9 since C is 9 semitones below A. So to get the octave number, i.e. the "4" in "A4", we just divide the note number by 12 semitones and add 4 since a note number 0 translate to A4.

Finally all that is left is to get the note itself, and to get this, we do a modulus operation and a switch case for the 12 different semitones. I figured there was no formula to determine the notes due to the uneven nature of having no semitone between E and F, and between B and C, so a switch case is ideal. If there is a formula, please do post it in the comments!

Flash Dynamic Sound Generation 1


I messed around with dynamic sound generation in Flash today, inspired by some of the interesting websites like Tone Matrix and Otomata. I created a Flash swf for testing frequencies and wave-forms.

At first I didn't know where to start so some search results turned up this useful link from Adobe. Also found this site which gave a really simple sample code which I decided to try out. However, the code did not produce any sound so I looked up the docs on the SampleDataEvent and worked from there.

Things I learnt :
  1. The number of samples should not be lower than 2048, as recommended by the docs. This is because it may cause the sound to stop playing if there is not enough data, which is why my computer did not produce any sound. The number of samples are just used as buffer and do not immediately play on the next update.
  2. The callback is only called when the buffer is running out of data to stream. I felt this was not clearly explained in the docs. So essentially setting the samples to 2048 or 8192 has no effect on the sound produced. When you update 8192 samples in one update, it just means it will take a longer duration to call the callback again to refill the buffer. However, the drawback of setting a higher sample number is that it will also take up more processing time for that update.
  3. The data is always played at 44100 Hz. This is stated in the extract function of the Sound class, however, it is not reiterated in the SampleDataEvent docs, so it confused me. I'll explain why this detail is important later in (7).
  4. Wikipedia taught me that the sin wave has a rather complex general form which we seldom see. I tried playing around the DC offset in Flash but I could not tell the difference between the sounds. In essence, we only need the simple form i.e. y = A * sin ( f*t ), where A is the amplitude and f is the frequency we want.
  5. Originally I was thinking that square, triangle and sawtooth waves had to be generated by Fourier series and adding sin waves together, which is what I remember from physics class. However, through Wikipedia I found that there are simpler methods to generate these waves. For e.g. square waves can be generated simply by just using the sign of the sin wave, i.e.:
    y = -A if sin (f*t ) < 0
    y = A if sin (f*t) > 0
    In code, this would be simply: y = (sin(f*t) > 0) ? A : -A;
  6. Originally I also thought that the speed of sound was required to generate real sound frequencies. This is because we need to map the wavelength into the generation process using the frequency equation, f = v/w. However, this is not the case as we just need to set the correct wavelength for the sound to be played in the air, so we do not need to account for velocity. In other words, frequency = 1/wavelength and this meant we could directly use the frequency in our equations.
  7. The units are important! As with all mathematical calculations, making sure the units are consistent is very important. At first I was trying out with f = 220 Hz; A = 0.25, i.e. using equation y = A * sin(f*t), I got y = 0.25 * sin (220*t). Although this seems correct, this gave me the wrong sound. The problem here is that I made the wrong assumption about the units for the equation. Instead of t being time, we are actually using samples instead. The samples are playing at 44.1kHZ mentioned in (3). Therefore, the correct equation is instead y = A*sin(f *(s/44100)), where s is the sample number. This took me a while to figure out so I hope it will save you some time.
  8. Keep in mind the periods of the waves. While figuring out how to generate the sawtooth and triangle wave forms, I got a different tone from the sine and square wave forms. I figured out that I needed to multiply 2π to the sine and square wave forms because they are using the sine function but not to the other wave forms.

Tuesday, 19 April 2011

Gamasutra Programming Jobs Word Clouds

I compiled all 122 of the Gamasutra Jobs related to programming, excluding scripting that are listed today and used http://www.wordle.net/ to create these word clouds:


Based on the Job Titles of the 122 jobs (click for larger view):


Based on the Job Descriptions of the 122 jobs (click for larger view):

Based on the Platforms listed in the 85 out of 122 jobs (click for larger view):
Data used


Some interesting observations I found about the current state of the games industry:

  • Senior developers are highly sought after.
  • Gameplay programmers are in demand perhaps due to the fact that many companies have switched to engines and tools.
  • Console platforms seem to be hiring more than mobile ones. This could be due to the fact that mobile developers are mostly startups.
Disclaimer: this data is just based on Gamasutra alone and only for today, so this information could be outdated easily or biased towards only the Gamasutra community.

Saturday, 28 August 2010

Automatic posting of shared links from Facebook to Blogspot

(skip to summary at bottom to skip my rants)

It's been awhile since I posted. Since then, there have been many changes in my life including my graduation from university and the embarkation on the working world. I have also learnt many more things as well as met many more people. I also reluctantly started using Facebook a year ago but now check it everyday and share links from friends, which brings me back... well, here... I figured that if I was sharing so many links everyday, and was rather unhappy with the fact that Facebook currently does not allow me to search the links or organize them better. Occasionally when I wanted to refer to a link I posted a month back, I had to click the "Load New Posts" several times under the links section before I could find the link. What made it worse was that now is the mobile age and the Facebook Mobile iPhone App lacks text searching functionality so it makes it hard to find a link. Therefore, I felt that collating them on this blog would be better in the long run, so that is what I've set out to do.

First, I searched online to see if Facebook could post to this blog automatically. However very little information turned up and I was quite disappointed because that would mean that I either might have to copy links manually from Facebook or have to do the reverse which is post on the blog and have it sent to Facebook, preferrably automatically.

Being a programmer means that I'm lazy and will never settle for a manual solution so I started to see if I could find out how to get Blogger/Blogspot to post to Facebook automatically. I found that the common solution was to get Facebook to read the RSS of this blog and it will automatically convert posts into Notes. Here is a great tutorial on how to do so: http://everything.typepad.com/blog/2009/01/how-to-add-your-blog-feed-to-your-facebook-profile.html However, I still was not satisfied with this solution because the main way I used Facebook was just for sharing links. As you can probably tell at the start of this post, I gave up the whole blogging thing, so I did not want to keep posting into my Facebook notes. I wanted it to post into Facebook links instead of notes!

Having some spare time to kill, I tried looking for other ways to get around this. Unfortunately, I kept finding the Facebook notes solution and I decided to go back to trying to see if there was a way to get Facebook to post to Blogger/Blogspot instead, which is the ideal solution anyway. Then I logged into Facebook and started to see if there was anything in the links section at all that would give me a hint. Then I found it! Apparently, Facebook has RSS for the links section of a user. Then Google did the rest of the magic and I found out that if I could get this RSS to email me whenever I posted something, I could forward the email to the Blogspot posting email and that should do the trick. Then I checked the Help section of Gmail to see if there was some setting that I could use, but it turned out that Gmail does not support having an RSS email you even though you may have a Google Reader account, so I found out about http://www.feedmyinbox.com/ which is exactly what I needed.

So in summary, in order to get Facebook to post to Blogspot, here's the steps you should do:
  1. Go to your Facebook profile
  2. Go to your links section ( This is not the same as your newsfeed section where you can see your friends' posts)
  3. Look for the "Subscribe to Links" area and copy the link of the "My Links" button. This is your RSS feed for your links posts from Facebook.
  4. Get Feedmyinbox to forward this RSS feed to your email account ( if you want a more direct route, you can also directly post to your blog, but beware that any admin messages from Feedmyinbox will appear publicly on your blog, so this is not advised!)
  5. Set up your Blogger/Blogspot posting email address. This should be under "Settings", then "Email & Mobile" tab.
  6. For Gmail users, you can set a filter to forward all messages from Feedmyinbox to your blog posting email address and this will effectively post the messages for you. For other emails, you have to figure out your own way to get the messages automatically forwarded.

Monday, 21 May 2007

Computer Graphics Lab 1 : Morph

Ok, this is another assignment from my computer graphics module. The first one in fact. We were to put in the code which could morph pictures.



How does it work? Well, first you got to watch the video once. Then notice the red lines near the end of the video? Those are the guides to the morph. What the program tries to do is move each red line in the source picture (cat) closer towards the corresponding red line in the alternate picture (dog). As it is moving the lines, it calculates the pixels which need to be stretched or changed during that frame according to a mathematical formula. Well, actually its abit more complicated than that but that's the gist.

For the video above, I am actually trying to show you the different modes of the program. What I did not show was the long computation time it took to calculate 24 frames for that second. It took about 3 to 4 seconds to compute each frame. So nope, morphing using this algorithm is not real-time! As for the modes, I first showed the source and target blended morph, then the source-only morph (cat), then the target-only morph (dog), then blended with the guides. Blended meaning an interpolation of transparency. So the cat is 0% transparent and the dog 100% on the first frame. The cat 50% and the dog 50% on the middle frame. The cat 100% and the dog 0% on the last frame.

I did not really find the assignment hard since we were given an algorithm to follow but I did learn alot from this assignment and was really amazed at how maths could be used to manipulate so many things. It was also only in this module that I realised Adobe Photoshop was all about powerful maths. Yup all your strange effects and tools are all essentially some kind of formula. Some are really complicated and thus the slow computation times and some are really straightforward and fast. Oh and I would also like to state that I did not do all the programming. Most of the framework was provided by the lecturer and we only had to fill up the morphing algorithm.

well that's all for today! (lucky i found out how to do the video stuff yesterday so this post only took a short time) Oh but i did find out more about the flv player today. A surprising fact that it can actually have a different frame rate from the swf it is contained in so that videos of different frame rates will all be played at its correct frame rate. This is unlike the rule where a swf contained in another swf will follow the frame rate of the parent swf. Also, the flvplayer can resize itself to fit the video it is play. This is a really wonderful feature because that means I can use one player for all my flv videos of different sizes and frame rates. Awesome.

More computer graphics stuff for the rest of this week! I have decided to make this week Academic-related Posts week.

Get Adsense

Want to earn money like me? Get Google Adsense now by clicking this