EVR.Animation.Introduction.Prompt = function(container)
{
   EVR.Graphic.call(this, container, null, null, ALIGN_BOTTOM);
   EVR.Animation.call(this, PROMPT_BLINK_RATE);
   this.set_proportions(1, null);
   this.place(0, -PROMPT_OFFSET);
   this.style();
   this.set_text(PROMPT_TEXT, PROMPT_FONT, PROMPT_COLOR, PROMPT_SIZE_RATIO);
}
EVR.Animation.Introduction.Prompt.prototype = new EVR.Graphic;
EVR.inherit(EVR.Animation.Introduction.Prompt, EVR.Animation);
EVR.Animation.Introduction.Prompt.prototype.style = function()
{
   this.css.letterSpacing = "5";
}   
EVR.Animation.Introduction.Prompt.prototype.sequence = function()
{
   if (this.attached)
   {
      this.remove();
   }
   else
   {
      this.append();
   }
}
EVR.Animation.Introduction.Prompt.prototype.remove = function()
{
   if (this.attached)
   {
      EVR.Graphic.prototype.remove.call(this);
   }
}
EVR.Animation.Introduction.Prompt.prototype.toString = function()
{
   return "[object EVR.Animation.Introduction.Prompt]";
}
EVR.include("animation/introduction/transmission/Projection.js");
EVR.Animation.Introduction.Transmission = function(
   container, black_hole, beam_count, jump, rate)
{
   this.container = container;
   this.black_hole = black_hole;
   this.colors = TRANSMISSION_COLORS;
   this.beam_count = beam_count;
   this.jump = jump;
   this.rate = rate;
   this.build_beams();
   this.build_projections();
}
EVR.Animation.Introduction.Transmission.prototype.build_beams = function()
{
   this.beams = [];
   for (var ii = 0; ii < this.beam_count; ii++)
   {
      this.beams.push(
	 new EVR.Beam(
	    this.container, this.colors[ii], this.black_hole.proportions[0], 0,
	    this.black_hole, ALIGN_CENTER));
   }
}
EVR.Animation.Introduction.Transmission.prototype.build_projections = function()
{
   this.projections = this.build_projection(0);
   var current = this.projections;
   for (var ii = 1; ii < this.beams.length; ii++)
   {
      current.next = this.build_projection(ii);
      current = current.next;
   }
}
EVR.Animation.Introduction.Transmission.prototype.build_projection =
function(index)
{
   return new EVR.Animation.Introduction.Transmission.Projection(
      this.beams[index], this.beam_count, this.jump, this.rate, this.black_hole,
      index);
}
EVR.Animation.Introduction.Transmission.prototype.redraw = function()
{
   for (var ii = 0; ii < this.beams.length; ii++)
   {
      this.beams[ii].draw();
   }
}
EVR.Animation.Introduction.Transmission.prototype.reset = function()
{
   var beam, projection = this.projections;
   while (projection)
   {
      beam = projection.beam;
      beam.proportions[1] = 0;
      beam.set_dimensions(0, 0);
      beam.place(0, 0);
      projection = projection.next;
   }
}
EVR.Animation.Introduction.Transmission.prototype.erase = function()
{
   var projection = this.projections;
   while (projection)
   {
      projection.stop();
      projection.beam.remove();
      projection = projection.next;
   }
}
EVR.Animation.Introduction.Transmission.prototype.toString = function()
{
   return "[object EVR.Animation.Introduction.Transmission]";
}
EVR.Animation.Introduction.Transmission.Projection = function(
   beam, beam_count, jump, rate, black_hole, index)
{
   EVR.Animation.call(this, rate);
   this.beam = beam;
   this.beam_count = beam_count;
   this.step = jump / 2;
   this.rate = rate;
   this.black_hole = black_hole;
   this.index = index;
   this.steps_per_jump = INTRODUCTION_STEPS_PER_JUMP;
   this.set_limit();
   this.steps = 0;
}
EVR.Animation.Introduction.Transmission.Projection.prototype =
   new EVR.Animation;
EVR.Animation.Introduction.Transmission.Projection.prototype.sequence =
function()
{
   this.beam.grow(INTRODUCTION_BEAM_GROWTH_RATE);
   if (this.beam.proportions[1] >= this.black_hole.proportions[1])
   {
      this.stop();
      this.beam.proportions[1] = this.black_hole.proportions[1];
      this.beam.draw();
      this.play("shift", 100, -1);
      if (typeof(this.next) != "undefined")
      {
	 this.next.play(null, 500);
      }
      else
      {
	 this.black_hole.play(null, 1000, -BLACK_HOLE_FADE_IN_SPEED);
      }
   }
}
EVR.Animation.Introduction.Transmission.Projection.prototype.set_limit =
function()
{
   this.step_limit = (this.beam_count - this.index) * this.steps_per_jump;
}
EVR.Animation.Introduction.Transmission.Projection.prototype.shift = function()
{
   if (this.steps < this.step_limit)
   {
      this.beam.move(0, -this.step);
      this.steps++;
   }
   else
   {
      this.steps = 0;
      this.stop();
   }
}
EVR.Animation.Introduction.Transmission.Projection.prototype.toString =
function()
{
   return "[object EVR.Animation.Introduction.Transmission.Projection]";
}
EVR.include("sound/controls/Controls.js");
EVR.include("sound/audio/Audio.js");
EVR.include("sound/Prompt.js");
EVR.Sound = function(container, song)
{
   EVR.Graphic.call(this, container, null, null, ALIGN_BOTTOM_RIGHT);
   this.choose_method();
   this.set_proportions(SOUND_WIDTH, SOUND_HEIGHT);
   this.set_z(SOUND_Z_INDEX);
   this.append();
   this.controls = new EVR.Sound.Controls(this);
   this.set_song(song);
   this.prompt = new EVR.Sound.Prompt(this);
}
EVR.Sound.prototype = new EVR.Graphic;
EVR.Sound.prototype.choose_method = function()
{
   if (!!document.createElement("audio").canPlayType)
   {
      this.audio = new EVR.Sound.Audio.HTML5(this);
   }
   else if (!!document.all)
   {
      this.audio = new EVR.Sound.Audio.BGSound(this);
   }
   else
   {
      this.audio = new EVR.Sound.Audio.Embed(this);
   }
   console.write(this.audio);
}
EVR.Sound.prototype.set_song = function(name)
{
   this.audio.set_song(name);
}
EVR.Sound.prototype.hide = function()
{
   this.controls.hide();
   this.prompt.hide();
}
EVR.Sound.prototype.show = function()
{
   this.controls.show();
   this.prompt.show();
}
EVR.Sound.prototype.draw = function()
{
   EVR.Graphic.prototype.draw.call(this);
   if (!!this.controls)
   {
      this.controls.draw();
   }
   if (!!this.prompt)
   {
      this.prompt.draw();
   }
}
EVR.Sound.prototype.toString = function()
{
   return "[object EVR.Sound]";
}
216.73.216.106
216.73.216.106
216.73.216.106
 
September 13, 2013

from array import array
from time import sleep

import pygame
from pygame.mixer import Sound, get_init, pre_init

class Note(Sound):

    def __init__(self, frequency, volume=.1):
        self.frequency = frequency
        Sound.__init__(self, self.build_samples())
        self.set_volume(volume)

    def build_samples(self):
        period = int(round(get_init()[0] / self.frequency))
        samples = array("h", [0] * period)
        amplitude = 2 ** (abs(get_init()[1]) - 1) - 1
        for time in xrange(period):
            if time < period / 2:
                samples[time] = amplitude
            else:
                samples[time] = -amplitude
        return samples

if __name__ == "__main__":
    pre_init(44100, -16, 1, 1024)
    pygame.init()
    Note(440).play(-1)
    sleep(5)

This program generates and plays a 440 Hz tone for 5 seconds. It can be extended to generate the spectrum of notes with a frequency table or the frequency formula. Because the rewards in Send are idealized ocean waves, they can also be represented as tones. Each level has a tone in its goal and a tone based on where the player's disc lands. Both play at the end of a level, sounding harmonic for a close shot and discordant for a near miss. The game can dynamically create these tones using the program as a basis.

I'm also building an algorithmically generated song: Silk Routes (Scissored). Here is an example of how it sounds so far.