Dept of | by Philip Likens

Playing a Note of a Certain Length

Previously: Playing a Note of a Certain Frequency

So now that we have a pitch, how do we know how long a sound will be?  One second of audio generated in Flash requires 44,100 pieces of sample data.  So if we’re writing 8192 samples each time we call our function, we would have to call our function at least six times.  However, if we call our function six times, we end up with 49,152 samples – which is more than one second of audio.  So we have a problem.

Some of you might be saying, well why don’t we call our function 6 times, but drop the number of samples we write each time to 7350 – that way we have the perfect number of samples to make 44,100.  Your thinking is correct for this example, but there is at least one problem with that scenario.  What if you want to produce a quarter-second sound?  A half-second sound would work just fine, we would call our function three times instead of six.  But it is impossible to call a function one and one half times.  So what can we do?

My suggestion is to keep the sample size at 8192 and clip the audio where you need it.  If we know one second is 44,100 samples, we also know 11,025 is a quarter second (44,100 / 4 = 11,025).  In audio, a sound with an amplitude or volume set at 0 is silent.  So to play a quarter-second sound I would call my function twice which will produce 16,384 samples.  I only want to play 11,025 samples of real audio though, so I’ll let the sine wave write the first 11,025 samples, then I’ll fill the rest of the sample data with 0s.  Those 0s will be represented as silence and I’ll get a note that is only a quarter second long.

For example, consider the code:

  1. var mySoundLength:int = 11025;
  2. var mySound:Sound = new Sound();
  3. function sineWaveGenerator(event:SampleDataEvent):void {
  4. var frequency:Number = 440;
  5. for ( var c:int=0; c<8192; c++ ) {
  6. if(c+event.position < mySoundLength) {
  7. event.data.writeFloat( Math.sin( Number(c+event.position) * (frequency * 2 * Math.PI) / 44100) * 0.25 );
  8. event.data.writeFloat( Math.sin( Number(c+event.position) * (frequency * 2 * Math.PI) / 44100) * 0.25 );
  9. } else {
  10. event.data.writeFloat(0);
  11. event.data.writeFloat(0);
  12. }
  13. }
  14. }
  15. mySound.addEventListener(SampleDataEvent.SAMPLE_DATA,sineWaveGenerator);
  16. mySound.play();

In line 1 we set the length of the sound we want to play.  In line 6 we’re checking to make sure our current position within our audio is less than our sound length.  If it is, we’re writing our audio as normal.  If we’re past the length of the note we want to play, write 0 volume to our SampleDataEvent.

Next up: Playing a Note Without the Hideous Popping or Clipping

Tags: , , , , , , , , ,

Leave a Reply