Detuneしてみる

2DCOで、片方のpitchをちょっとずらしてみる感じですね!
でも、それどうやって実現するの?ってことで、
Cassis::Mixerの紹介も兼ねて実装してみます。

use v5.14;
use strict;
use warnings;

use Cassis;
use constant SAMPLING_RATE => 44100;

my $dco1 = Cassis::DCO::Saw->new( fs => SAMPLING_RATE );
my $dco2 = 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 = ();
foreach my $tune ( 0.0, 0.005, 0.02 ) {
    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;
        $dco1->set_pitch( 4.0 + $pitch );
        $dco2->set_pitch( 4.0 + $pitch + $tune );

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

        my $mixer_out = Cassis::Mixer::mix(
            { src => $dco1->exec( num => scalar(@{$eg_out}) ), volume => 1.0 },
            { src => $dco2->exec( num => scalar(@{$eg_out}) ), volume => 0.5 }
        );

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

        push @wav, @{$amp_out};
    }
}

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

ちょっとコードが長くなったけど、
これでDetuneの効果が分かって貰えるかと思います。

うーん、位相ずらしとか、
そういうのもissueに上げておきますかね。

おしまい。

Leave a Comment