Skip to content

Instantly share code, notes, and snippets.

@zed9h
Created July 17, 2009 03:54
Show Gist options
  • Save zed9h/148853 to your computer and use it in GitHub Desktop.
Save zed9h/148853 to your computer and use it in GitHub Desktop.
random ambient sound (pink/red noise)
#!/usr/bin/perl
use strict;
use warnings;
use Math::FFTW;
use Audio::DSP;
use Time::HiRes qw(time);
my $amp = 0xffff;
my $len = 0xfff;
my $rate = 48000;
my $hard = .5; # 0=pink, 1=pink..red
my $start = time;
my $epsilon = 0.0001;
my $dsp = new Audio::DSP(
buffer => $len*2,
channels => 1,
format => 16,
rate => $rate,
);
$dsp->init() or die $dsp->errstr();
sub min($$) { $_[0] < $_[1] ? $_[0] : $_[1] }
sub max($$) { $_[0] > $_[1] ? $_[0] : $_[1] }
sub clamp($$$) { $_[1] < $_[0] ? $_[0] : $_[1] > $_[2] ? $_[2] : $_[1] }
for (;;) {
my $white = [map {rand($amp-1)-$amp/2} 0..$len];
my $coeff = Math::FFTW::fftw_dft_real2complex_1d($white);
my $n = scalar(@$coeff)/2;
my $t = time;
my $pow = (1+$hard/2)+($hard/2)*sin($t/20); # 1=pink, 2=red/brown
my $nyquist = $rate/2;
my $f = 1;
for (3..8) {
$f *= .5+.5*abs(sin($t/$_));
}
my $start_freq = 100 + 400 * $f;
my $start_i = int(.99+$n*$start_freq/$nyquist);
$start_freq = $start_i/$n*$nyquist;
for(my $i=$start_i; $i<$n; $i++) {
my $p = $i/($n-1);
my $a = $p*$nyquist/$start_freq;
my $b = log($a)/log(2);
my $c = (2**$b)**$pow;
$f = 1./$c;
#print "".($p*$nyquist)." $start_freq $a $b $c : $f\n";
$coeff->[$i*2+0] *= $f;
$coeff->[$i*2+1] *= $f;
}
for(my $i=1; $i<$n; $i++) {
my $p = $i/($n-1);
my $f = 1;
for (3..8) {
$f *= .9+.1*sin($t/$_);
}
$coeff->[$i*2+0] *= $f;
$coeff->[$i*2+1] *= $f;
}
my $pink = Math::FFTW::fftw_idft_complex2real_1d($coeff);
$n = int(.99+$rate*0.001);
for(my $i=0; $i<$n; $i++) {
my $f = $i/$n;
$pink->[ $i] *= $f;
$pink->[-$i] *= $f;
}
$dsp->datacat(pack "s*", @$pink);
$dsp->write() or die $dsp->errstr();
my $delta = time - $start;
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday) = gmtime($delta);
$sec += $delta - int($delta);
# my $n = scalar(@$coeff)/2;
# for(my $i=1; $i<$n; $i+=int($n/60)) {
# printf "%6d %s\n", $i/$n*$nyquist, '#' x int(log(1+sqrt(
# $coeff->[$i*2+0]**2 +
# $coeff->[$i*2+1]**2
# ))*4);
# }
$|=1;
# print "";
printf "\r";
printf "%dd ", $yday if $yday;
printf "%2dh ", $hour if $hour||$yday;
printf "%2dm ", $min if $min ||$hour||$yday;
printf "%6.3fs ", $sec if $sec ||$min ||$hour||$yday;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment