ディレイっぽいエフェクトを実装してみる

手を抜いてると思われるかも知れませんが、
あながち、間違ってはいないですね!

use v5.14;
use strict;
use warnings;

use Cassis;
use constant SAMPLING_RATE => 44100;

my $dco = Cassis::DCO::Saw->new( fs => SAMPLING_RATE );
my $filter = Cassis::Iir2::LPF->new( cutoff => 0.3, q => 1.0 );

my $eg = Cassis::EG->new(
    fs      => SAMPLING_RATE,
    adsr    => [ 0.03, 0.1, 0.9, 0.3 ],
    curve   => 0.5
);

my @wav = ();
{
    my @pitch_table = (
        -9 / 12, # C
        -7 / 12, # D
        -5 / 12, # E
        -4 / 12, # F
        -2 / 12, # G
         0 / 12, # A
         2 / 12, # B
        (-9 / 12) + 1.0 # C(ここから1オクターブ上がる)
    );

    while ( @pitch_table ) {
        my $pitch = shift @pitch_table;
        $dco->set_pitch( 4.0 + $pitch );

        my $eg_out;
        if ( @pitch_table ) {
            $eg->trigger( gatetime => 0.1 );
            $eg_out = $eg->exec( num => SAMPLING_RATE * 0.8 );
        }
        else {
            $eg_out = $eg->one_shot( gatetime => 0.1 );
        }

        my $dco_out = $dco->exec( num => scalar(@{$eg_out}) );

        my $amp = Cassis::Amp->new();
        my $amp_out = $amp->exec(
            src => $filter->exec( src => $dco_out ),
            mod_volume => {
                src => $eg_out,
                depth => 1.0
            }
        );

        push @wav, @{$amp_out};
    }

    my @fb_buf = @wav;
    my $fb_gain = 0.2;
    my $delay = 0.25;

    my $n = int(SAMPLING_RATE * $delay);
    my @tmp = map { 0.0; } 1..$n;
    while ( 0.1 < $fb_gain ) {
        push @wav, @tmp;
        unshift @fb_buf, @tmp;

        my $mixer_out = Cassis::Mixer::mix(
            { src => \@wav, volume => 1.0 },
            { src => \@fb_buf, volume => $fb_gain }
        );

        @wav = @{$mixer_out};
        @fb_buf = @{$mixer_out};
        $fb_gain = $fb_gain ** 1.06;
    }
}

Cassis::File::write(
    file => 'delay.wav',
    fs => SAMPLING_RATE, channels => [ \@wav ] );

とは言うものの、フィードバック時のゲインの減衰させ方で悩みました。
これで良いのかも、ちょっと分かんないです。。。
エフェクトの調整は、フィードバックさせる回数とかの方がいんですかね。

おしまい。

Leave a Comment