Audio-NoiseGen
view release on metacpan or search on metacpan
lib/Audio/NoiseGen.pm view on Meta::CPAN
$stream
%note_freq
init
play
G
sine
silence
noise
white_noise
triangle
square
envelope
combine
split
sequence
note
rest
segment
formula
hardlimit
amp
oneshot
lowpass
highpass
generalize
);
our %EXPORT_TAGS = (
all => [ @EXPORT_OK ]
);
=head1 INITIALIZATION AND PLAY
=head2 init($api, $device, $sample_rate)
This sets up our L<Audio::PortAudio> interface. All parameters are optional, and without any you will get the default provided by PortAudio.
=cut
sub init {
my $api = shift || Audio::PortAudio::default_host_api();
my $device = shift || $api->default_output_device;
$sample_rate = shift || 48000;
# $sample_rate = shift || 20000;
$time_step = (1/$sample_rate); # 2 * (1/48000) = 0.0000416666
$stream = $device->open_write_stream(
{
channel_count => 1,
},
$sample_rate,
8000, # some sort of buffer size?
# 0
);
}
# sub import {
# my $class = shift;
# # if(grep { /^:init$/ } @_) {
# # Audio::NoiseGen::init();
# # }
# $class->SUPER::import(@_);
# }
sub log10 {
my $n = shift;
return log($n)/log(10);
}
sub db {
my $sample = shift;
return (20 * log10(abs($sample)+0.00000001));
}
=head2 play(gen => $gen, filename => $filename)
C<$filename> is optional.
Invokes the C<$gen> and sends the resulting samples to the output device (soundcard).
=cut
# Play a sequence until we get an undef
my $mon = 0;
sub play {
my %params = generalize( @_ );
my $gen = $params{gen};
my $filename = $params{filename} && $params{filename}->();
# sox -r 48k -e floating-point -b 32 out.raw out.wav
my $file;
if($filename) {
open $file, '>', $filename
or die "Error opening $filename: $!";
}
while (1) {
my $raw_sample = '';
for(1..1000) {
# while(1) {
my $sample = $gen->();
if(defined $sample && ($sample > 1 || $sample < -1)) {
print "CLIP: $sample\n";
$sample = $sample > 1 ? 1 : -1;
}
# print "Sample: $sample\n";
if(!defined $sample) {
$stream->write($raw_sample);
print $file $raw_sample if $file;
return;
}
# printf "dB: %0.05f\n", db($sample)
# unless $mon++ % 100;
$raw_sample .= pack "f*", $sample;
}
# unless $mon++ % 1000;
# print "Sending sample block...";
my $write_available = $stream->write_available;
# printf "Buffer: %d\n", $write_available
# if $write_available < 1000;
# unless $mon++ % 100;
$stream->write($raw_sample);
( run in 1.332 second using v1.01-cache-2.11-cpan-5e09290becf )