NAME

Audio::NoiseGen - Unit Generator Based Sound Synthesizer

SYNOPSIS

use Audio::NoiseGen ':all';

# Connect to your sound engine/hardware
Audio::NoiseGen::init();

play( gen =>
  envelope(
    attack => 0.2,
    sustain => 14.5,
    release => 0.2,
    gen =>
      combine(
        gens => [
          segment(notes => '
            E D C D
            E E E R
            D D D R
            E E E R
            E D C D
            E E E/2 E
            D D E D C
          '),
          segment(notes => 'A2 R R R'),
          segment(notes => 'C3/2 E3/4 E3/4 C3/2 F3 R'),
        ],
      ),
  )
);

DESCRIPTION

"Unit Generators" have long been a method to synthesize digital sound (music, dare I say). This module provides a suite of such generators. You first create an instance of a generator, and then each time that instance is invoked it returns a sample.

PACKAGE VARIABLES

These variables can be exported if you want. They are used by some of the generators to help calculate things like timing.

  • $sample_rate - samples/second sent to soundcard

  • $time_step - 1/$sample_rate to ease calculations

  • $pi - Er.... pi :)

  • %note_freq - map of note names to frequencies

INITIALIZATION AND PLAY

init($api, $device, $sample_rate)

This sets up our Audio::PortAudio interface. All parameters are optional, and without any you will get the default provided by PortAudio.

play(gen => $gen, filename => $filename)

$filename is optional.

Invokes the $gen and sends the resulting samples to the output device (soundcard).

UNIT GENERATORS

sine({ freq => 440 })

Generates a sine-wave.

amp( amount => 0.5, gen => $g )

Amplify the output of $g. If amount is greather than 1 this will make it louder, less than one to make it quieter.

silence()

Just return silence forever.

white_noise()

Return random samples.

triangle( freq => $freq )

Triangle wave.

square( freq => $freq )

Square wave.

envelope( gen => $g, ... )

Build up a simple envelope. So far this supports attack, sustain, and release (I need to implement decay).

This will fade the volume up for $attack seconds (linear), keep it there for $sustain seconds, and then fade down for $release seconds (linear).

Returns undef at the end of the release.

combine( gens => [ ... ] )

Plays each of the provided generators all at once.

Once all the generators return undef, combine will return undef. Subsequent calls will start it over.

sequence( gens => [ ... ] )

Play a list of generators, one after another. Plays the first generator until it returns undef, then goes on to the second, and so on. Returns undef when it completes the last generator in it's sequence, and then keeps returning undef after that.

note( note => 'C#' )

Plays a named note, looking it up in %note_freq. Actually builds an envelope for the note, so it can take a subref 'instrument' to use for the actual sound.

Note that 'instrument' isn't a generator, it is a generator-creator that will be passed a freq. The default is \&sine. Tricky.

You can also pass any of the evelope parameters. It defaults to zero attack and release, and 0.1 second sustain.

rest( length => 3 )

Play silence for a fixed set of time, 'length', in seconds.

segment( notes => 'A B C#' )

Generate a sequence of notes by parsing the 'notes' param. Pretty minimal for now.

formula( formula => sub { $_*(42&$_>>10) } )

Plays a formula. Takes 'formula', 'bits', and 'sample_rate'. 'bits' defaults to 8, 'sample_rate' defaults to 8000.

Formula uses $_ instead of 't', but is otherwise similar to what is described at http://countercomplex.blogspot.com/2011/10/algorithmic-symphonies-from-one-line-of.html.