7月
08

同じHTMLでもブラウザによって微妙に見え方が異なる場合があるのはウェブ制作者なら周知の通りです。特にIE6, IE7はW3C標準に準拠しないMS独自の仕様でレンダリングしていたため、レイアウトが崩れてしばしばウェブ制作者を悩ませてきました。しかしIE8になってようやく改善されてきたようで、見え方の違いに悩まされることも少なくなりました。

IEはWindows標準のブラウザだけでなく、独立したコントロールとしても動作するので、自前のアプリケーションに組み込んで使用することも可能です。ところがここでちょっと困った問題に直面しました。たとえIE8がインストールされていても、自前のアプリケーションに組み込まれたブラウザはデフォルトではIE7互換モードで動作してしまうのです。IE8は過去のバージョンとの互換性を保ちながらレンダリングするモードがあり、標準ブラウザではメニューから切り替えることが可能です。ところが自前のアプリケーションに組み込まれたブラウザの互換モードを切り替える方法がどうしてもわかりませんした。

そこでウェブを検索してみると情報が見つかりました。どうやらレジストリのあるキーにアプリケーションを登録してやれば、そのアプリケーションに組み込まれたブラウザはIE8ネイティブモードで動作する仕組みのようです。設定すべきレジストリのキーは以下の通りです。

HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION

すごく深い階層です(笑)。このキーがない場合は作成し、そこに次のサブキーを書き込みます。

サブキー名:アプリケーションの実行ファイル名
値:DWORD値として8000(10進)

実行ファイル名はフルパスではなく、ファイル名のみです。これで登録されたアプリケーションはIE8のネイティブモードで動作するようになります。IE7互換モードに戻したいときはサブキーを削除します。プログラムの起動時にレジストリに書き込むようにすればよいでしょう。なおレジストリを操作しますので、プログラミングにあたっては十分注意して下さい。

8月
19

以前『緯度経度から距離と方位を求める方法』という記事を書きましたが、プログラマの方には具体的なソースがないとわかりにくいかもしれないので、JavaScriptのプログラムを書いてみました。中身は単純ですので他の言語にも容易に移植できると思います。ソースは下記からダウンロードできます。

JavaScriptのソース(右クリックで保存してください)

下のフォームに2地点の緯度と経度を入力して「計算」ボタンをクリックすると、距離と方位角を計算して表示します。

前に説明しましたように、これは簡易的な計算ですので、地球の丸みが無視できないような広い範囲には適用できません。たとえば札幌-鹿児島間とかは無理です。逆にGPSに記録されたログのポイント間など、数百メートル程度のごく狭い範囲に限れば、厳密な方法で求めたものとほとんど変わらない精度が得られます。

なお緯度経度を入力する際は度分秒単位ではなく、度単位つまり十進法に直してから入力する必要がありますのでご注意ください。

地点1:
緯度

°
経度

°


地点2:
緯度

°
経度

°


←クリックすると結果を下に表示します。


距離

m
方位角

°
8月
17

窓関数を用いる理由

FFTを行う際によく窓関数というものが用いられます。しかし何のために使うのかよくわからずに何となく使っている方も多いのではないでしょうか。後学のためにここで少しだけ説明しておきましょう。

まずその前にFFTを行う際の大前提について知っておかなければなりません。フーリエ変換の定義によれば、「あらゆる周期関数は正弦波と余弦波の重ね合わせで表すことができる」ことが知られています。ここで「周期関数」というところに深い意味があるのですが、要するに周期関数とはあるパターンが一定の周期で繰り返される関数のことを言うわけです。逆に言えば、フーリエ変換を行うためには周期関数でなければならないということになります。

しかしコンピュータでFFTを行う場合、無限のサンプルを取るわけにはいきませんから、当然ある限られた範囲のサンプルを取って変換を行うことになります。特にFFTの場合はサンプル数に制約があって、1024, 2048, 4096・・・といった2のべき乗個しかとることができません。たとえばサンプル数を4096に選んだとすると、音声信号を処理する場合、波形を4096個ずつのサンプルに区切ってFFTを行い、スペクトルに変換するわけです。ここで先の大前提と矛盾することにお気づきでしょうか? 周期関数であるということは、先頭から4096サンプル取ったとすれば、その次の4096サンプルも、そのまた次の4096サンプルもまったく同じパターンを繰り返さなければならないことになります。もし音声の周波数が正確にわかっていて、その周期にピッタリ合わせて4096サンプル取ったとすれば、完全な周期関数にすることも理論上は可能でしょう。しかし現実には周波数があらかじめわかっていることはほとんどなく(そもそもFFTを行うのは周波数を求めるためです)、しかも周波数は時間とともに変化することが普通です。したがって一般的には有限のサンプル数で区切った波形が周期関数になっている可能性は限りなくゼロに近いのです。このことは下の図をご覧いただくとおわかりでしょう。サンプル数をNとした場合、Nサンプルごとに同じパターンが繰り返されれば周期関数になっていますが、一般にはそうなる可能性はほとんどなく、常に2)の状態になっています。

関数の周期性

2)のように周期性が成り立たない状態でFFTを行うと何が問題になるのでしょうか? 有限のNサンプルについてフーリエ変換を行う場合、そのNサンプルとまったく同じパターンが前後に永遠に繰り返されていることが前提になります。もし1)のように周期性が成り立っている場合、区間の初めと終わりの値が同じであることに注目して下さい。この場合、最初のNサンプルを永遠に繰り返していっても当然滑らかにつながります。しかし2)のように区間の両端の値が異なっていると、そのつなぎ目で不連続が生じてしまいます。もっと平たく言えば、波形が「カクカク」してしまうということですね。

一般に滑らかではない不連続性のある関数をフーリエ変換すると、そのスペクトルは低周波から高周波まで非常に広い範囲に分散します。たとえば矩形波のような不連続関数をフーリエ変換してみると、無限の高周波成分を含んでいることがわかりますし、もっと極端なデルタ関数のフーリエ変換はすべての周波数成分を均等に含むものになります。ですから不連続性のある波形をフーリエ変換すると、本来の周波数以外に「余分な」スペクトルがたくさん出てきて分解能が悪くなるということになるのです。

たとえば周波数が一定の正弦波をフーリエ変換したとします。もしその周波数に対応する周期がFFTのサンプリング周期と完璧に一致して周期関数になっていれば、スペクトルは1本しか立たないはずです。なぜなら正弦波は倍音成分を一切含まないからです。しかし周波数が少しでもずれていれば前述の理由により、本来の周波数以外に余分なスペクトルがいっぱい出てきてしまいます。これは実際にやってみればすぐわかります。この状態が下図に示す(A)の矩形窓に相当します。

代表的な窓関数

これから窓関数について説明しますが、実は何も考えなかったら暗黙のうちに(A)の矩形窓を使っていることになるのです。定義から言うとサンプル要素nが0からN-1までの間は1で、それ以外はすべて0ということですが、要するに波形から単純にNサンプルずつ切り出すことと等価です。この場合、区間の両端における不連続性については何も考慮されていませんから、正弦波をフーリエ変換したとしても図のようにスペクトルは大きく広がったものになってしまいます。

そこでこの不連続性をできるだけ目立たなくするために「本来の」窓関数というものを使うわけです。一般に窓関数w(n)は次式のように波形x(n)に掛け合わせることによって使用します。

f(n) = w(n) x(n)

そしてこのf(n)をフーリエ変換することによって所望の結果を得るわけです。

窓関数については多くの学者によってたくさん考案されていますが、特に簡単かつ実用性の高いものとして次の2つを紹介しておきます。

(B)ハニング窓

これはハンという人によって考案されたので「ハン窓」と呼ぶこともありますが、次のハミング窓と語呂がよいことからハニング窓と呼ばれることが多いようです。定義は図の(B)に示されています。この窓関数の特徴は区間の端に向かってなだらかに小さくなっていき、両端は必ずゼロになるということです。ゼロになるわけですから、元の波形がどんなに不連続であっても両端の値は必ずゼロで滑らかにつながるわけですね。なおnはN-1までだから右端でゼロにならないじゃないかと思われる方がいるかもしれませんが、これは離散化しているためであり、連続量つまりNを無限大にした極限では0になることがおわかりでしょう。

ハニング窓を適用して正弦波をフーリエ変換した場合のスペクトルは、矩形窓を使う場合に比べてぐっと周波数の幅が狭くなり、ピークがはっきりと現れるようになります。

(C)ハミング窓

これはハニング窓を改良したもので、形はまったく同じですが、両端がゼロにならないところが特徴です。したがって不連続性がわずかながら残っているわけです。両端を完全にゼロにしてしまうと区間の両端でのふるまいが無視されてしまうため、それを防ぐためにこのようにしたのでしょう。

ハミング窓を適用して正弦波をフーリエ変換した場合のスペクトルは、ハニング窓を使った場合とよく似ていますが、不連続性が若干残っている分、裾野の広がりはわずかに大きくなります。その代わりピークはより鋭くなって、周波数分解能が高まるという特徴を持っています。

以上、代表的な窓関数について説明しましたが、実際はもっと多くの窓関数が存在して用途に応じて使い分けられます。しかし音声処理でFFTを行う場合の主な目的はスペクトル解析や周波数推定(採譜)ですから、特にハミング窓について知っておけばほぼ十分であるともいえるでしょう。

8月
04

FFTの扱い方

音声処理を扱うプログラムで非常によく用いられるものにFFT(高速フーリエ変換)があります。これは従来非常に時間のかかる計算であったフーリエ変換のアルゴリズムを改良して飛躍的に高速化したものですが、こういうものはすでに優秀なライブラリがいくらでも提供されていますので、その仕組みまで知る必要はありません。プログラマーとしては単にライブラリを呼び出して結果を得られればよいだけのことです。

音声処理でFFTを行う目的としては、時間の関数である波形を周波数の関数であるスペクトルに変換するために主に用いられます。つまりどのくらいの周波数の音がどのくらいの割合で含まれているか(スペクトル)を求めるときに使うわけです。ところが実際にFFTのライブラリを使おうとするとどうやって入力を与え、出力を得ればよいのか悩んでしまうことがあります。それは複素数という厄介なものが登場するからですが、特に数学の苦手な方にとってはそれだけでアレルギー反応を起こしてしまうようです。

本来、複素数というものは高校数学あたりで習っているはずなのですが、理系の大学に進んだ人以外、たいがい忘れているようです。ここで複素数についてもう一度復習しておきましょう。

complex_number

複素数というものは一般に実部と虚部に分けて考えることができます。任意の複素数をxとすると、
x = a + b i
という形に表すことができます。ここでaを実部、bを虚部といいます。そして i は虚数単位と呼ばれ、2乗すると-1になるという変な性質を持っています。つまり i × i = -1です。

もう少し話を具体化して音声信号を扱うことにすると、一定時間ごとにサンプリングされた音声信号、すなわち波形x[n]は
x[n] = a[n] + b[n] i
という形に離散化して表すことができます。プログラムではこれを配列として扱うことはおわかりですね。

さてこの波形x[n]をフーリエ変換する場合、どうすればよいのでしょうか? 通常FFTのライブラリは入力・出力ともに複素数になっています。つまり実部と虚部の2組の配列を渡すか、または独自に定義された複素数型を使って受け渡しを行います。同様に結果も複素数として返ってきます。ところが、初めての人はまずここで悩んでしまうのではないでしょうか?

実は波形を入力として渡す場合は完全な実数と考えられますので、実部のa[n]だけを渡せば十分です。つまり虚部b[n]はすべて0とします。そしてFFTの関数を呼び出せばよいわけです。

厄介なのは出力の方です。実数である波形をフーリエ変換した結果は一般的に複素数になります。やりたいことは周波数のスペクトルを求められればよいのですが、この複素数をどのようにして扱えばよいのか途方に暮れてしまうことでしょう。

複素数というものは一般に上の図のような複素平面を用いて表します。任意の複素数x[n]は、実部a[n]を横軸、虚部b[n]を縦軸とする直交座標上の一点として表すことができます。ここで少し見方を変えて実部・虚部という表現から振幅と位相という表現に置き換えることを考えます。これは要するに直交座標から極座標への変換と同じです。振幅Aは三平方の定理によりa[n]およびb[n]の2乗の和の平方根をとったものになることはおわかりでしょう。同様に位相θは簡単な三角関数でb[n]/a[n]の逆正接で求められます。

ここでスペクトルを求める場合に重要なのは振幅の方です。位相スペクトルというものもあるのですが、人間の聴覚にとっては振幅スペクトルが大きな意味を持つので、通常は振幅スペクトルだけを考えれば十分です。ですからFFTを行って得られた結果から、上の式にしたがって振幅Aを求めてやればよいということになります。これが普通に音のスペクトルと呼んでいるものです。

なお振幅とよく似たものにパワー(電力)があります。一般にパワーPは振幅の2乗に比例しますので、
P = A × A
すなわちAの2乗がパワーになります。パワースペクトルという呼び方をすることもありますが、その場合は振幅の2乗の分布を表していると考えればよいでしょう。上の式で振幅Aを2乗すると平方根が取れますから、単にa[n]の2乗とb[n]の2乗の和になります。

またスペクトルはよく対数を取ってデシベルで表すことが多いですが、振幅(電圧)とパワー(電力)で定義が少し異なります。すなわち
振幅の場合  dB = 20log A
パワーの場合 dB = 10log P
のように前の係数が2倍だけ異なります。これはよく考えるとPはAの2乗ですから、対数を取るとそれが2倍になって前に出てくると考えれば理解できます。

次にフーリエ変換した結果の周波数はどうやって求めればよいのでしょうか。FFTの制約により、ポイント数は1024, 2048, 4096・・・といった2のべき乗しかとることができませんが、FFTを行った結果はこれらの要素数をもった配列になっているわけで、それぞれの配列要素が表す周波数を知りたいわけです。

FFTのポイント数をN、サンプリング周波数をfsとしたとき、n番目の配列要素(もちろんnは0からN-1まで)に対応する周波数f[n]は次の式で求めることができます。

discreted_frequency

ここでn = Nを代入してやればfsに等しくなりますから、感覚として理解できるでしょう。つまりFFTを行って得られる結果の周波数範囲は0からfs(離散化しているので実際は一つ分少ない)までになります。ところがこれがすべて有効というわけではありません。よく知られているようにサンプリング周波数がfsであるとき、離散化して表現可能である周波数の上限はfs/2に限られます。これをナイキストの定理といい、fs/2のことをナイキスト周波数と呼んだりします。一般にFFTを行って得られるパワースペクトルは下図に示すようにナイキスト周波数を境にして左右対称になります。

power_spectrum

つまり右半分は左半分の虚像であって意味はないということですね。したがってFFTの結果で実際に有効なのはn = 0 ~ N/2 – 1までの配列要素ということになります。

最後に具体的なイメージを持ってもらうために、実際に音声処理でよく使われる数値を代入してみましょう。まずサンプリング周波数fsはCDと同じ44100Hzが最もよく用いられますね。そしてFFTのポイント数ですが、これは多ければ多いほど周波数分解能が上がることは上の式からわかりますが、逆にサンプル時間を長く取る必要があるため、時間分解能は低下してしまいます。目的によっても異なりますが、一般的には両方の兼ね合いから4096くらいを選ぶことが多いようです。その場合の周波数分解能は
44100Hz / 4096 = 10.7Hz
ということになります。もちろんナイキスト周波数はfsの1/2で22050Hzですね。したがってこのケースでは、n番目の配列要素に対応する周波数f[n]は
f[n] = 10.7 × n (Hz)
ということになり、FFTの結果が有効な上限周波数は
10.7Hz × (2048 – 1) = 21903Hz
ということになります。

2月
23

GoogleのサイトにもThe “Hello, World” of Google Maps v3として解説してありますが、まず地図を表示させるために最低限必要な枠組みについて解説しましょう。任意の地点を中心にしてただ地図を表示するだけのサンプルですが、すべてはここから始まります。あとは必要に応じて付け加えていけばよいわけです。

<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
	function initMap() {
		var mapOptions = {
			zoom: 15,
			center: new google.maps.LatLng(34.685334, 135.832742),
			mapTypeId: google.maps.MapTypeId.ROADMAP
		};
		var map = new google.maps.Map(document.getElementById("mapdiv"), mapOptions);
	}
</script>
</head>
<body onload="initMap()">
	<div id="mapdiv" style="width: 100%; height: 100%"></div>
</body>
</html>

サンプルプログラム

まずheadブロックのmeta name=”viewport”というタグですが、これはiPhoneなどの携帯端末でアクセスする際に地図を常に画面いっぱいに表示させるための「おまじない」です。とりあえずこれはそのまま入れておけばOKです。

そして次のAPIを読み込むためのscriptタグですが、V2とは違ってAPIキーは必要ありません。もっともこれは現在試験中のためで、正式運用になった際には必要になるのかもしれません。?以降にあるsensorというパラメータはtrueまたはfalseのいずれかを指定しなければなりません。これはGPS機能付きの携帯電話など自分の位置を捕捉できる場合はtrueを指定し、その他一般のPC向けにはfalseを指定します。

それに続くscriptタグが地図を表示するためのJavaScriptの本体部分です。ここではinitMapという一つの関数を定義し、bodyタグのonloadイベントで読み込みと同時に実行されるようにしています。

地図を表示するためには、まず地図を入れるためのコンテナを指定します。これはV2と同じで、divタグでボックス領域を指定し、id属性で適当な名前を付けます。ここでは”mapdiv”としておきます。

そして地図そのものを表すクラスMapのコンストラクタを呼び出してオブジェクトを生成してやればよいわけですが、V2とちょっと違うのはクラス名の前には必ず”google.maps.”という修飾子を付けなければならない点です。Javaではおなじみですが、これは名前空間と呼ばれるもので、他人が作ったクラスと混同されないようにユニーク性を保証するためのものです。少し面倒なような気もしますが、これはこれで洗練されているといえるでしょう。

Mapクラスのコンストラクタは2つの引数をとり、第1引数には地図を表示するボックスのDOMオブジェクトを指定します。これはV2と同じくgetElementByIdで先ほど指定したid=”mapdiv”のDOMを取ってやればOKです。そして第2引数には地図の初期状態を決めるためのオプションを指定します。ここでは中心座標とズームレベル、それに初期マップタイプを指定しますが、その他にもさまざまなオプションを指定可能です。

オプションを指定するにはJSONと呼ばれる形式でプロパティ名とその値を指定します。これは{}の中にカンマで区切っていくつでも列挙することができ、それぞれ「プロパティ名: 値」という形になります。ここではズームレベルを15とし、中心座標を(34.685334, 135.832742)としています。なお緯度経度を表すオブジェクトはLatLngクラスのコンストラクタを呼び出すことにより生成しますが、もちろんここでも名前空間を付けなければなりません。そして次のmapTypeIdというプロパティは初期マップタイプを指定するもので、ここではMapTypeIdクラスの定数として定義されているROADMAPを指定しています。これは普通の道路地図という意味です。もしSATELLITEを指定したならば航空写真になります。

とりあえずこれだけ書けば地図を表示させることが可能ですので、中心座標をいろいろ変えながらサンプルプログラムで確認してみて下さい。

2月
13

Google Mapsといえば今ではすっかり当たり前になったスクロール・ズームが可能な地図の草分け的存在であり、現在は2006年にリリースされたAPI version2が正規版として使われています。ところで最近新しいバージョンであるAPI version3がリリースされ、利用可能になっています。version2に比べてどこが変わったのでしょうか? とりあえず現在わかっている点だけ拾ってみます。

◎良くなった点

  • AndroidやiPhoneなどの携帯端末に最適化した表示が可能になった。
  • APIキーが不要になった。

従来のV2は主にデスクトップ環境で使用されることを想定したもので、モバイル環境では荷が重かったのですが、V3ではモバイル端末に特化した高速化が図られ、軽快に表示できるようになっています。また従来必要であったAPIキーが不要になったので、サイトごとに取得する手間が省け、より簡単に使えるようになりました。

◎悪くなった点

  • OverviewMapがなくなった。
  • Earth APIと連動した3D表示ができなくなった。

OverviewMapというのはメインのマップの右下に表示される小さな地図のことですが、V3では今のところ同様のものが実装されていないようです。また3D表示も今のところ対応していません。V3は現在実験という位置付けであり、V2で実装されていたもののいくつかが利用できませんが、これらは将来的に実装されていくものと思われます。

ということで、機能的に充実しているV2に比べると少し劣る部分もありますが、モバイル環境での使用を考えているならば試してみる価値はあるのではないかと思います。

1月
29

PHP4→PHP5への移行に伴い、array_merge関数の仕様が変わっていますので注意が必要です。

PHP5ではarray_merge関数の引数はすべて配列でなければなりません。

array_merge($array1, $array2, $array3, ・・・);

PHP4では次のようなコードも許されていましたが、

$array1 = array("a", "b", "c");
$result = array_merge($array1, "d");
print_r($result);

PHP5ではこのコードは無効とされ、結果はヌルになってしまいます。

PHP5では次のように明示的に配列として定義しなければなりません。

$array1 = array("a", "b", "c");
$result = array_merge($array1, array("d"));
print_r($result);

実はこのようなコードがXOOPSの古いモジュールに含まれていたのですが、サーバー側で勝手にPHPのバージョンが上がったため正常に動作しなくなっていました。エラーメッセージも表示されないので発見が困難です。ご注意下さい。

1月
28

最近は一眼レフを含めたほとんどのデジカメで動画が撮影できるようになり、ハイビジョン画質に対応したものも増えて、かつてのビデオ専用機に迫る品質を達成してきています。これからはますますスチルカメラとビデオカメラの境界が曖昧になっていくことでしょう。ところでこういったデジカメで撮影した動画のフォーマットは一昔前までならWindows標準のAVI形式であることが多かったのですが、最近では圧縮性に優れたMPEG-4などの形式を採用したものが増えてきました。ファイル容量が小さくなること自体は歓迎なのですが、困ったことにこれらの形式はWindowsに標準装備されているムービーメーカーで編集することができないのです(Windows 7では直接編集できるようになりました)。ムービーメーカーで直接編集できるのは拡張子が.AVIか.WMVのファイルだけで、.MP4などのファイルを投入しようとしても受け付けてくれません。実際にビデオ撮影していると余分な部分をカットしたり、細切れになったクリップを一つにまとめたいという要求が必ず出てきますが、そのためだけに高価なビデオ編集ソフトを購入するのもばからしい話です。実はフリーソフトを使ってムービーメーカーで編集可能にする方法がありますのでご紹介しましょう。

その前にまず動画のフォーマットについて理解しておく必要があります。動画のフォーマットというのは少々複雑で、大きく分けて「コンテナ」と「コーデック」の部分から成り立っています。コンテナというのはいわば「入れ物」のことで、これは.AVI, .MOV, .WMV, .MP4. .3GPといったファイル形式に相当します。こういったファイル形式は入れ物だけを提供するもので、その中身までは規定していません。それに対してコーデックというのは動画をどのように圧縮するかという符号形式を規定するもので、エンコード(圧縮)とデコード(伸張)の両方について規定しているわけです。コーデックはさらに音声と映像に分かれ、音声ではPCM, MP3, AACなどの形式があり、映像ではMotion JPEG, WMV, mpeg-4, H.264などの形式があります。動画のフォーマットについて概念的に示すと、下図のようになります。

video_formats

コンテナとコーデックの組み合わせについてはすべてが可能というわけではありませんが、ある程度自由に組み合わせることができます。たとえば一般的なデジカメの動画ではコンテナがAVIでコーデックがMotion JPEGのものと、コンテナがMOVでコーデックがMotion JPEGのものの両方が存在します。ムービーメーカーではコーデックがMotion JPEGであれば編集することが可能ですが、もしコンテナだけをMOVからAVIに入れ換えることができればMOV形式のMotion JPEGも編集可能になるわけです。

さて、ここで最近一般的になってきたH.264方式で記録できるデジカメについて考えてみましょう。H.264は画質と圧縮効率の両方に優れ、現在最強のコーデックとも言われています。メーカーにもよりますが、H.264方式の動画はたいていMP4形式のコンテナに格納されるのが一般的です。これはApple社のQuickTimeでは再生できますが、Windowsメディアプレイヤーでは再生することができません。もちろんムービーメーカーに読み込むことも不可能です。それはWindowsが標準でH.264のコーデックを持っていないことと、MP4形式に対応していないことの両方によります。ここでもしFFMPEGなどのフリーソフトを使ってAVIあるいはWMV形式に変換してやればムービーメーカーに読み込むことが可能になります。ところがこの変換は再エンコーディングを行うため、必ず画質の劣化を伴います。いったん圧縮したものをもう一度圧縮することになるからです。さらに再エンコーディングは大変時間のかかる処理のため、大量の動画を変換するにはそれだけでやる気が失せる作業になってしまうことでしょう。

それでは再エンコーディングを行うことなく、フォーマットを変更することが可能なのか? 実はそれを行うためのフリーソフトとしてMP4Cam2AVI Easy Converterというものがあり、これを使えばH.264のコーデックに手を加えることなく、コンテナだけをAVIにごっそり入れ換えることが可能なのです。この場合、再エンコーディングを行わないので画質の劣化はなく、しかも非常に高速です。それならMP4形式で撮影した動画ファイルをすべてAVI形式に変換してやればムービーメーカーに読み込ませることができるはずです。

しかしそれだけではまだ十分ではありません。なぜならWindowsはH.264のコーデックを持っていないため、たとえコンテナがAVIであってもまだ再生することができないからです。そこでH.264のコーデックをどこかから持ってくればよいわけですが、そのためにffdshowというフリーソフトが存在します。ffdshowはフリーのコーデックパッケージであり、これをインストールするだけで現在使われているほとんどのコーデックが再生可能になるものです。もちろんH.264も入っていますので、これでようやくAVIに変換したH.264コーデックの動画が編集可能となるわけです。

では仕組みがわかったところで実際の作業に移りましょう。まず先に紹介したMP4Cam2AVI Easy Converterとffdshowのサイトから最新版をダウンロードして下さい。先にffdshowからインストールするのがいいでしょう。インストール時にいろいろ質問されますが、とりあえず全部デフォルトでNextを押していけばOKです。それがインストールできたら次にMP4Cam2AVI Easy Converterのインストールを行います。こちらはZIPファイルを解凍するだけでOKです。

そしてMp4Cam2AVI.exeをダブルクリックするとソフトが起動します。まず最初に初期設定を行います。メインメニューから[Settings]→[Program Mode]をクリックし、”Advanced (no video re-coding)”を選びます。これで映像を再エンコーディングしない設定になります。

mp4cam2avi_setting1

次に右のAudio formatのタブから”Source audio (no recompression)”を選びます。これで音声を再エンコーディングしない設定になります。その上のActionのタブはデフォルトで”Convert & join”になっていますが、そのままでは複数のファイルが一つに連結されてしまいますので、”Batch convert”に変更することをおすすめします。これで入力ファイルそれぞれについて個別に変換することが可能になります。以上で設定は終わりです。

mp4cam2avi_setting2

実際に変換を行うには、まずSource directoryタブでソースファイルのあるディレクトリを選択します。すると下のfile list modeタブにファイル一覧が表示されますので、変換したいMP4ファイルを選択します。複数のファイルはCtrlキーあるいはShiftキーを押しながらクリックすることで選択できます。

mp4cam2avi_filelist

あとは画面右下にあるStartボタンを押すだけで変換が開始されます。マシンパワーにも依存しますが、3分程度のクリップなら数秒で終了するでしょう。再エンコーディングすることを考えれば圧倒的な速さです。変換されたファイルはtarget directoryで指定された場所に出力されます。Batch convertを選んだ場合は元のファイル名の拡張子だけを.AVIに変えたものになります。こうやって変換されたAVIファイルは中身がH.264コーデックになっていますが、ffdshowが入っていればメディアプレイヤーで再生することができますし、ムービーメーカーに読み込むことも可能になっています。どうぞお試し下さい。
Read more…

12月
29

オンラインヘルプを開くなど、アプリケーションからブラウザを立ち上げたいことはよくあります。これもVCLには専用の関数などは用意されていませんが、Windows APIを呼び出すことにより簡単に実行できます。ブラウザを立ち上げるにはWindows APIのShellExecute関数を使用します。

ShellExecute(
    NULL,
    "open",
    "http://www.logical-arts.jp/",    // ここにURLを指定
    NULL,
    NULL,
    SW_SHOWNORMAL
);

引数の多い関数ですが、第3引数にURLを渡しさえすれば、あとは上記のままで構いません。第2引数の”open”はNULLでもOKです。第6引数のSW_SHOWNORMALはウィンドウを通常のサイズで開いてアクティブにするという意味です。

この関数を実行すると、既定のブラウザが起動して指定したURLを表示します。

12月
29

Canvasに描画する際、全体ではなく、ある矩形領域の中にだけ描画したいときがあります。こういう処理をクリッピングといいます。たとえばグラフを描画する際など、枠外にはみ出した部分は描画されると困るので必須の処理になります。ところがVCLにはクリッピングを行う機能が用意されていません。そこでWindows APIの助けを借りることになります。ソースコードは次のような感じです。

Graphics::TBitmap* bitmap = new Graphics::TBitmap();
bitmap->SetSize(400, 400);
HRGN hrgn = CreateRectRgn(100, 100, 300, 300);    // クリッピング領域を作成
SelectClipRgn(bitmap->Canvas->Handle, hrgn);    // クリッピング領域を設定
DeleteObject(hrgn);    // ハンドルを解放

// 描画処理

SelectClipRgn(bitmap->Canvas->Handle, NULL);    // クリッピング領域を解除

// 別の描画処理

delete bitmap;

上記の例ではクリッピング領域を(100, 100)と(300, 300)を対角線とする矩形に設定しています。CreateRectRgn関数でクリッピング領域のハンドルを作成し、SelectClipRgn関数でCanvasにクリッピング領域を設定するという流れになります。

CreateRectRgn関数の4つの引数にはクリッピングしたい領域を左・上・右・下の座標で指定します。この関数は設定した領域のハンドルを返します。

SelectClipRgn関数の第1引数にはCanvasのHandleプロパティを指定します。第2引数にはCreateRectRgn関数で作成した領域のハンドルを指定します。領域のハンドルは用が済んだらDeleteObject関数で解放しなければなりません。

SelectClipRgn関数の第2引数にNULLを指定すると、クリッピングを解除することができます。