Perlでミョンミョンした音を作る
今日はCassisを開発するときに使ってるスクリプトを公開します。
あとはパラメータをファイルから入力できるようにして、
サンプルスクリプトとしてリポジトリに追加する予定です。
package MySynth; use strict; use warnings; use Cassis; sub new { my $class = shift; my %args = @_; my $fs = ( exists $args{fs} ) ? $args{fs} : 44100; bless { samples => [], fs => $fs, modules => { DCO1 => Cassis::DCO::Saw->new( fs => $fs ), DCO2 => Cassis::DCO::Tri->new( fs => $fs ), LPF => Cassis::Iir2::LPF->new( cutoff => 0.01, q => 6.0 ), LFO1 => Cassis::Osc::Pulse->new( fs => $fs ), LFO2 => Cassis::Osc::Sin->new( fs => $fs ), AMP => Cassis::Amp->new(), EG1 => Cassis::EG->new( fs => $fs, adsr => [ 0.03, 0.1, 0.5, 0.5 ], curve => 0.5 ), EG2 => Cassis::EG->new( fs => $fs, adsr => [ 0.03, 0.4, 0.2, 0.5 ], curve => 0.5 ) } }, $class; } sub exec { my $self = shift; my %args = @_; my ( $dco1, $dco2, $lpf, $lfo1, $lfo2, $amp, $env1, $env2 ) = map { $self->{modules}->{$_}; } qw(DCO1 DCO2 LPF LFO1 LFO2 AMP EG1 EG2); $dco1->set_pitch( $args{pitch} - 0.01) if ( exists $args{pitch} ); $dco2->set_pitch( $args{pitch} - 1.0 ) if ( exists $args{pitch} ); $lfo1->set_freq( 2000 ); $lfo2->set_freq( 2200 ); $amp->set_volume( 0.5 ); $env1->trigger( gatetime => 1.0 ); $env2->trigger( gatetime => 0.5 ); my $lfo1_out = $lfo1->exec( num => $args{num} ); my $lfo2_out = $lfo2->exec( num => $args{num} ); my $dco1_out = $dco1->exec( num => $args{num}, mod_pitch => { src => $lfo1_out, depth => 0.2 } ); my $dco2_out = $dco2->exec( num => $args{num}, mod_pitch => { src => $lfo2_out, depth => 0.1 } ); my $filter_out = $lpf->exec( src => mix($dco1_out, $dco2_out, 0.5), mod_cutoff => { src => $env2->exec( num => $args{num} ), depth => 0.5 } ); my $amp_out = $amp->exec( src => $filter_out, mod_volume => { src => $env1->exec( num => $args{num} ), depth => 1.0 } ); push @{$self->{samples}}, @{$amp_out}; } sub write { my $self = shift; my %args = @_; $args{sf} = $self->{sf}; $args{channels} = [ $self->{samples} ]; Cassis::File::write( %args ); } sub mix { my ( $src1, $src2, $gain ) = @_; my $n = scalar( @{$src1} ); my @dst = map { ($src1->[$_] + $src2->[$_]) * $gain; } 0..($n - 1); return \@dst; } package main; use strict; use warnings; my %NOTE_TO_PITCH = ( C => -9 / 12, D => -7 / 12, E => -5 / 12, F => -4 / 12, G => -2 / 12, A => 0 / 12, B => 2 / 12 ); my $s = MySynth->new(); foreach ( qw(C4 D4 E4 F4 G4 A4 B4 C5) ) { if ( my ( $note, $octave ) = m/([\w])(\d)/i ) { print 'pitch: ', $octave + $NOTE_TO_PITCH{$note}, "\n"; $s->exec( pitch => $octave + $NOTE_TO_PITCH{$note}, num => 44100 * 0.5 ); } else { warn 'cannot parse => ', $_; } } $s->write( file => 'sample.wav' );
まだ、音作りのコツがつかめてないのですが、
実際は、ランダムパラメータでWAVとパラメータと出力して、
気に入った音が見つかったら詰めていこうと思っています。
個人的に、非常に満足しております。
おしまい。
Leave a Comment