=encoding euc-jp =head1 NAME =begin original MIDI::Track -- functions and methods for MIDI tracks =end original MIDI::Track -- MIDIトラックのための関数とメソッド =head1 SYNOPSIS use MIDI; # MIDI::Track その他を use する $taco_track = MIDI::Track->new; $taco_track->events( ['text_event', 0, "I like tacos!"], ['note_on', 0, 4, 50, 96 ], ['note_off', 300, 4, 50, 96 ], ); $opus = MIDI::Opus->new( { 'format' => 0, 'ticks' => 240, 'tracks' => [ $taco_track ] } ); ...etc... =head1 説明 =begin original MIDI::Track provides a constructor and methods for objects representing a MIDI track. It is part of the MIDI suite. =end original MIDI::Trackは、MIDIトラックを表現するオブジェクトに対する コンストラクタとメソッドを提供する。 =begin original MIDI tracks have, currently, three attributes: a type, events, and data. Almost all tracks you'll ever deal with are of type "MTrk", and so this is the type by default. Events are what make up an MTrk track. If a track is not of type MTrk, or is an unparsed MTrk, then it has (or better have!) data. =end original 現在MIDIトラックはタイプ、イベント、データという三つの属性を持っている。 あなたが扱うほとんど全てのトラックは"MTrk"タイプのトラックだ。 そしてこれがデフォルトのタイプである。イベントは、MTrkトラックを構成している。 もしあるトラックがMTrkタイプでないか、あるいはMTrkとして解析されない場合、 それはデータということだ。 =begin original When an MTrk track is encoded, if there is data defined for it, that's what's encoded (and "encoding data" means just passing it thru untouched). Note that this happens even if the data defined is "" (but it won't happen if the data is undef). However, if there's no data defined for the MTrk track (as is the general case), then the track's events are encoded, via a call to C. =end original MTrkトラックがエンコードされる時、そこに定義済みのデータがあるなら、それが エンコードされる(「データをエンコードする」とは、データを未接触のものへと 送るこをと意味する)。データが""で定義されていてもエンコードされることに注意 (データがundefになっているならエンコードされない)。しかし、定義済みデータが MTrkトラックにない場合(これはよくあることだ)、トラックが有するイベントが エンコードされる。これはCの呼び出しを通じて行われる。 =begin original (If neither events not data are defined, it acts as a zero-length track.) =end original (もしどのイベントも定義されていないなら、0サイズのトラックとして振舞う。) =begin original If a non-MTrk track is encoded, its data is encoded. If there's no data for it, it acts as a zero-length track. =end original 非MTrkタイプのトラックがエンコードされるなら、トラックにあるデータはエンコード される。トラックにデータが無い場合は、0長サイズのトラックとして振舞う。 =begin original In other words, 1) events are meaningful only in an MTrk track, 2) you probably don't want both data and events defined, and 3) 99.999% of the time, just worry about events in MTrk tracks, because that's all you ever want to deal with anyway. =end original つまり、(1)イベントはMTrkタイプのトラック内部でのみ意味を持つ。 (2)定義されたデータとイベントの両方を必要とはしないだろう。 (3)あなたの時間の99.999%はMTrkトラック内のイベントに気をまわすことになる。 なぜなら、それがあなたが関わろうとすることの全てだからだ。 =head1 コンストラクタとメソッド =begin original MIDI::Track provides... =end original MIDI::Trackは以下のものを提供する。 =over =item MIDI::Track->new({ ...options... }) =begin original This returns a new track object. By default, the track is of type MTrk, which is probably what you want. The options, which are optional, is an anonymous hash. There are four recognized options: C, which sets the data of the new track to the string provided; C, which sets the type of the new track to the string provided; C, which sets the events of the new track to the contents of the list-reference provided (i.e., a reference to a LoL -- see L for the skinny on LoLs); and C, which is an exact synonym of C. =end original 新しいトラックオブジェクトを返す。デフォルトでMTrkタイプになる。これはたぶん あなたが望むものだろう。任意のオプションとして無名ハッシュを渡せる。 モジュールは四つのオプションを認識する:Cは新規のトラックデータに 与えられた文字列をセットする。Cは新規のトラックのタイプに与えられた 文字列をセットする。Cは新規のトラックのイベントに与えられたリスト リファレンスの内容をセットする(配列の配列へのリファレンス。正確な情報は Lを参照すること)。そして CはCと同義。 =item $new_track = $track->copy =begin original This duplicates the contents of the given track, and returns the duplicate. If you are unclear on why you may need this function, consider: =end original このメソッドはトラックの内容を複製し、オブジェクトを返す。 もしこの機能がなぜ必要なのかよくわからない場合は、次の例を考えてみよう。 $funk = MIDI::Opus->new({'from_file' => 'funk1.mid'}); $samba = MIDI::Opus->new({'from_file' => 'samba1.mid'}); $bass_track = ( $funk->tracks )[-1]; # $funkの最後尾のトラック push(@{ $samba->tracks_r }, $bass_track ); # $sambaの最後尾のトラックにする &funk_it_up( ( $funk->tracks )[-1] ); # $funkの最後尾のトラックを修正 &turn_it_out( ( $samba->tracks )[-1] ); # $sambaの最後尾のトラックを修正 $funk->write_to_file('funk2.mid'); $samba->write_to_file('samba2.mid'); exit; =begin original So you have your routines funk_it_up and turn_it_out, and they each modify the track they're applied to in some way. But the problem is that the above code probably does not do what you want -- because the last track-object of $funk and the last track-object of $samba are the I. An object, you may be surprised to learn, can be in different opuses at the same time -- which is fine, except in cases like the above code. That's where you need to do copy the object. Change the above code to read: =end original つまり、あなたはfunk_it_upとturn_it_outというルーチンをつくり、何らかの方法で それぞれのトラックを修正することになる。しかし問題は、上記のコードではあなたの 望むことをやってくれないだろうということだ。$funkの最後尾の トラックオブジェクトと$sambaの最後尾のトラックオブジェクトが I<同じオブジェクト>だからだ。驚くかもしれないが、一つのオブジェクトが別の オプスの中に同時に存在しうる(上のようなケースの除けば、これはこれで良い)。 だからオブジェクトをコピーする必要がある。上記のコードを変更すると: push(@{ $samba->tracks_r }, $bass_track->copy ); =begin original and what you want to happen, will. =end original これであなたの望んだとおりになるだろう。 =begin original Incidentally, this potential need to copy also occurs with opuses (and in fact any reference-based data structure, altho opuses and tracks should cover almost all cases with MIDI stuff), which is why there's $opus->copy, for copying entire opuses. =end original ついでにいうと、このようなコピーの必要性が、オプスにおいても生じる(そして 実際、リファレンスに基づくどんなデータ構造でも生じる。オプスとトラックは MIDI要素のほとんど全てのケースをカバーしなければならないにもかかわらず)。 これがオプスを丸ごとコピーするために$opus->copyが存在する理由である。 =begin original (If you happen to need to copy a single event, it's just $new = [@$old] ; and if you happen to need to copy an event structure (LoL) outside of a track for some reason, use MIDI::Event::copy_structure.) =end original (単一のイベントをコピーする必要があるなら、単に$new = [@$old]でよい。 何らかの理由で一つのトラックを越えてイベント構造(リストのリスト)を コピーする必要が出たらMIDI::Event::copy_structureを使うこと。) =item $track->events( @events ) =begin original Returns the list of events in the track, possibly after having set it to @events, if specified and not empty. (If you happen to want to set the list of events to an empty list, for whatever reason, you have to use "$track->events_r([])".) =end original トラックのイベントリストを返す。あるいは、@eventsを指定し、それが空でなければ その値がセットされる(理由は何であれ、リストイベントに空リストをセットしたい ならば、"$track->events_r([])"を使わなければならない)。 =begin original In other words: $track->events(@events) is how to set the list of events (assuming @events is not empty), and @events = $track->events is how to read the list of events. =end original つまり、(@eventsは空でないとして)$track->events(@events)はイベントリストの セット方法で、@events = $track->eventsはイベントリストの取得方法である。 =item $track->events_r( $event_r ) =begin original Returns a reference to the list of events in the track, possibly after having set it to $events_r, if specified. Actually, "$events_r" can be any listref to a LoL, whether it comes from a scalar as in C<$some_events_r>, or from something like C<[@events]>, or just plain old C<\@events> =end original トラックのイベントリストへのリファレンスを返す。あるいは、$events_rを指定すると リファレンスがセットされる。実際のところ、"$events_r"はリストのリスト(LoL)への リファレンスでありさえすればよいので、C<$some_events_r>からだろうと、 C<[@events]>からだろうと、古き簡素なC<\@events>からだろうと構わない。 =begin original Originally $track->events was the only way to deal with events, but I added $track->events_r to make possible 1) setting the list of events to (), for whatever that's worth, and 2) so you can directly manipulate the track's events, without having to I the list of events (which might be tens of thousands of elements long) back and forth. This way, you can say: =end original もともと$track->eventsがイベントを扱う唯一の方法だった。だが私が $track->events_rを付け加えたのは、(1)イベントリストを何らかの有意義な理由で 丸括弧()にセットできるようにするため。(2)(10000要素の長さにもなるような) イベントリストを前後でI<コピー>しなくても、直接トラックイベントを操作できる ようにするためである。そこでこのように書くことができる: $events_r = $track->events_r(); @some_stuff = splice(@$events_r, 4, 6); =begin original But if you don't know how to deal with listrefs outside of LoLs, that's OK, just use $track->events. =end original だが配列の配列を越えてリストリファレンスの扱い方を知らなくても、大丈夫。 $track->eventsを使えばよい。 =item $track->type( 'MFoo' ) =begin original Returns the type of $track, after having set it to 'MFoo', if provided. You probably won't ever need to use this method, other than in a context like: =end original $trackのタイプを返す。'MFoo'を与えれば、それがセットされる。たぶん次のような 文脈以外では、このメソッドを使う必要が生じることはないだろう: if( $track->type eq 'MTrk' ) { # 普通の場合 give_up_the_funk($track); } # それ以外なら処理を続けよう! =begin original Track types must be 4 bytes long; see L for details. =end original トラックタイプは4バイト長でなければならない。 詳細はLを参照のこと。 =item $track->data( $kooky_binary_data ) =begin original Returns the data from $track, after having set it to $kooky_binary_data, if provided -- even if it's zero-length! You probably won't ever need to use this method. For your information, $track->data(undef) is how to undefine the data for a track. =end original $trackからデータを返す。$kooky_binary_dataを与えれば、それがセットされる。 これは0サイズのデータでもよい!たぶんこのメソッドを使う必要が生じることは ないだろう。参考までにいうと、$track->data(undef)は、 トラックデータを未定義にする方法である。 =item $track->new_event('event', ...parameters... ) =begin original This adds the event ('event', ...parameters...) to the end of the event list for $track. It's just sugar for: =end original $trackのイベントリストの最後にイベント('event', ...parameters...)を 付け加える。これは次のコードの構文糖に他ならない: push( @{$this_track->events_r}, [ 'event', ...params... ] ) =begin original If you want anything other than the equivalent of that, like some kinda splice(), then do it yourself with $track->events_r or $track->events. =end original もしもこれ以上のこと、例えばsplice()のようなことをしたいなら、 $track->events_rや$track->eventsを使って自分自身でやること。 =item $track->dump({ ...options... }) =begin original This dumps the track's contents for your inspection. The dump format is code that looks like Perlcode you'd use to recreate that track. This routine outputs with just C, so you can use Cを使うことになる。私はこのルーチンをMIDI::Opus::dumpだけから 利用される内部ルーチンにしようとした。だが、特定のトラックだけを ダンプしたい人にとって便利になるよう図った。このルーチンがどのような 動作をするのか本当に知りたいなら、ソースを見てもらいたい。 =back =head1 著作権 Copyright (c) 1998-2002 Sean M. Burke. All rights reserved. This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 作者 Sean M. Burke C