Audio::PortAudio(実践編2)

たぶん、予想通りだと思うんだけど、
それだとつまらないので、cutoffを変化させる波形を複雑にしてみた。

use strict;
use warnings;
use Cassis;
use Audio::PortAudio;

use constant SAMPLING_RATE => 44100;
use constant INT16_MAX => 0x7FFF;

play();

sub play {
    my ( $frames_per_buffer, $stream_flags ) = ( 512, undef );
    my $api = Audio::PortAudio::default_host_api();
    printf STDERR "Going to play via %s\nCtrl+c to stop...", $api->name;
    my $device = $api->default_output_device;
    my $stream = $device->open_write_stream( {
            channel_count => 1, # 1:mono, 2:stereo
            sample_format => 'int16' #  'float32', 'int16', 'int32', 'int24', 'int8', 'uint8'
        },
        SAMPLING_RATE,
        $frames_per_buffer,
        $stream_flags,
    );

    my $noise = Cassis::Noise->new( speed => 0.3 );
    my $osc1 = Cassis::DCO::Sin->new( fs => SAMPLING_RATE, freq => 10.0 );
    my $osc2 = Cassis::DCO::Sin->new( fs => SAMPLING_RATE, freq => 10.02 );
    my $filter = Cassis::Iir2::LPF->new( cutoff => 0.25, q => 1.0 );

    # Infinite loop...
    while ( 1 ) {
        my $wa = $stream->write_available;

        my $mixer_out = Cassis::Mixer::mix(
            {
                src => $osc1->exec( num => $wa ),
                volume => 0.5
            },
            {
                src => $osc2->exec( num => $wa ),
                volume => 0.5
            }
        );

        my $filter_out = $filter->exec(
            src => $noise->exec( num => $wa ),
            mod_cutoff => {
                src => $mixer_out,
                depth => 0.1
            }
        );

        my $buf = pack( 's*', map {
            int( (($_ < -1.0) ? -1 : ((1.0 < $_) ? +1 : $_)) * INT16_MAX );
        } @{$filter_out} );

        $stream->write( $buf );
    }
}

2つの微妙に周期が異なる波形を足し合わせると、
その微妙に差異によって、打ち消したり、増幅したりするのが、
なんとなく分かって貰えると思う。

長い周期でcutoffを変化させて遊ぶのは本当に面白いですね!

おしまい。

Leave a Comment