開発備忘録

WPF(Xaml + C#)の話題を中心に.Net関連についてのブログです。

(Android)ログ出力ライブラリ"Timber"を使ってみる

Androidのログ出力ライブラリ"Timber"でログ出力機能を使ってみたのでメモ。

Timberについて

github.com

APIリファレンスはこちら。
Timber 3.0.1 API

動作環境

パッケージを導入する

  1. [File] - [Project Structure...] からパッケージを追加したいモジュールの[Dependencies]タブを選択する。
  2. 画面右側の[+]をクリック[Library dependency]を選択する。
  3. "com.jakewharton.timber:timber:4.5.1"と入力し、検索する。
  4. "com.jakewharton.timber:timber:4.5.1"を選択して[OK]ボタンをクリックする。
  5. build.grableに以下が追加されていればOK
compile 'com.jakewharton.timber:timber:4.5.1'

Timberを使う

Timberは初期化する際にログ出力機構のTreeを指定します。
以下は予め用意されているデバッグ用のTreeを設定しています。
リリース用のTreeは自前で作成する必要があるようです。

Timber.plant(new DebugTree());

使用する場合は通常のLogクラスと使い方は同じです。


サンプルを作成がてらログ出力機能を作りました。
以下のLoggerクラスはTimberのログ出力機能をラッパーです。
gist.github.com

initializeで初期化しているログTreeは以下のようになっています。
gist.github.com

後はこれを以下の様に使用します。
gist.github.com

これを実行するとLogCatには以下のようなログが出力されます。
f:id:iyemon018:20170912165732p:plain


あとはログの出力先をファイルにするなりクラッシュレポートを送信するなりすると使えそうです。

*1:2017年9月12日時点で最新版です。

ErgoDoxのキーマップ変更時にハマった現象と回避策について

先日、ErgoDoxを購入してウキウキで使用していたんですが、キーマップを変更する際にコンパイル環境の構築やらビルドやらでハマったのでその内容をメモします。
まず、前提条件として私は

  • Windowsユーザー
  • 普段は開発環境はVisual Studioを使用している。
  • キーボードはあんまり詳しくない。
  • C言語は殆どわからない。
  • Windows以外のOSのことは殆どわからない。
  • ErgoDox EZは9割衝動買い。

です。
なのでコンパイル環境は当然Windowsです。

続きを読む

MediaPlayer でファイル再生時のエラー回避方法について

またもやWPF のMediaPlayer ネタです。
MediaPlayer のイベントにMediaFailed がありますが、このイベントで以下のようなメッセージが出力される場合があります。

HRESULT からの例外:0xC00D11BA

これはWindows Media Player が出力している例外メッセージです。
MediaPlayer.Play() を呼び出した後にこの例外がスローされるのであれば、多くの場合、以下の内容が原因とされています。

  • サウンド ドライバーが最新でない。
  • 再生ファイルのコーデックが不足している。

など

しかし、再生中にたまにこの例外がスローされる事があります。
そうなった場合、再度MediaPlayer.Play() を実行しても楽曲が再生されません。

残念ながら確実に発生するオペレーションの確立と原因の究明までには至っていないため、この現象の発生を止めることはできません。
今回は"この現象が発生してももう一度楽曲を再生できる"ような対象法をまとめます。

動作環境

対策

正しいかどうかは別として、"エラー発生後に楽曲ファイルを再読読み込み"することで回避は可能です。
エラーの発生するコードは以下の様なものとしましょう。

	var mediaPlayer = new MediaPlayer();
	mediaPlayer.MediaFailed += (sender, e) =>
	{
		// HRESULT からの例外:0xC00D11BA
		// というエラーメッセージが出力される。
		Console.WriteLine(e.ErrorException);
	};
	
	mediaPlayer.Open(new Uri(@"Resources\sample.wav"));
	mediaPlayer.Play();

これをこう変えます。

	var mediaPlayer = new MediaPlayer();
	mediaPlayer.MediaFailed += (sender, e) =>
	{
		// HRESULT からの例外:0xC00D11BA
		// というエラーメッセージが出力される。
		Console.WriteLine(e.ErrorException);
		
		mediaPlayer.Close();
		mediaPlayer = null;
		
		mediaPlayer = new MediaPlayer();
		mediaPlayer.Open(new Uri(@"Resources\sample.wav"));
	};
	
	mediaPlayer.Open(new Uri(@"Resources\sample.wav"));
	mediaPlayer.Play();

イマイチ発生原因がつかめていないのでモヤモヤは残るのですが、今のところはこれで対応できているので良しとします。

MediaPlayer でファイル再生時のノイズ発生回避方法について

前回同様、WPF のMediaPlayer のお話です。
iyemon018.hatenablog.com

今回は楽曲ファイルの読み込み時ではなく、再生時に発生するノイズについてです。
このノイズも必ず発生するものではなく、特定の条件の楽曲ファイルと環境が揃わなければ発生しません。
かなり局所的な問題だと思われますが、とりあえずノイズの発生した環境は以下の通りです。

動作環境

  • OS : Windows 8.1 with Being (x86)*1
  • CPU : Intel Atom CPU Z3735F 1.33GHz
  • メモリ : 2GB
  • 楽曲ファイル : 再生時間300ミリ秒程度。1音目に振幅の大きい(例えばクリック音のような)楽曲に発生しやすい。

開発環境

現象

WPF のMediaPlayer の再生時に”1音目に振幅の大きい楽曲”を再生した場合にノイズが入る。
同じ楽曲を他のメディアプレイヤーで再生してもこの現象は発生しない。
また、動作環境によっては発生しない。
タブレットなどの低スペックPC上で発生するケースが多い。

原因

今のところわかっていません。
MediaPlayer は内部でWindows Media Player を使用しているのでWMPが怪しい気もするのですが、根本的な原因については今もわかっていません。

対策

楽曲ファイルの調整が可能であれば、楽曲ファイルの先頭に無音時間を10ミリ秒程度追加すると解消されます。
この方法であればコードの修正が必要ないため簡単に対応できるのですが、楽曲ファイルを編集できない場合は使えません。
他には、

  • 楽曲再生までに徐々に音量を上げる
  • 楽曲再生前にインターバルを持たせる

なども考えましたが、いずれも確実に修正できるという確証がなかったため試していません。

*1:Windows 10でも発生しますがハードウェアのスペックがわかりませんでした。

MediaPlayer でファイルオープン時のノイズ発生回避方法について

WPF でWAVE ファイルなどのメディアファイルを再生するとき、System.Windows.Media.MediaPlayer を使用していたのですが、複数ファイルを纏めてオープンしたときに何故か楽曲が少しだけ再生される現象が発生しました。
ここではその回避方法についてまとめています。

動作環境

実現したいこと

単純に複数の楽曲ファイルを予めロードすることで再生時のオーバーヘッドを軽減したい。
SoundPlayer クラス (System.Media) も試したのですが、「楽曲再生中に停止できない」「音量の調節機能が無い」ため、手っ取り早くMediaPlayer で実現することとなりました。

続きを読む

フォルダ内にあるMedia の再生時間を取得する(C#/WindowsAPICodePack)

特定のフォルダ内にあるメディア(MP3とかAVIとか)ファイルの再生時間を取得する方法のメモ

動作環境

WindowsAPICodePack は、以下の方法でインストールします。 www.nuget.org

以下、サンプルです。

var files = Directory.GetFiles(@"C:\work\");
foreach (var file in files)
{
    using (var shell = ShellObject.FromParsingName(file))
    {
        var property = shell.Properties.System.Media.Duration;
        if (property?.ValueAsObject != null)
        {
            var time = (ulong)property.ValueAsObject;
            Console.WriteLine($"{Path.GetFileName(file)} 再生時間[{TimeSpan.FromTicks((long)time)}]");
        }
        else
        {
            Console.WriteLine($"{Path.GetFileName(file)} 該当プロパティなし。");
        }
    }
}

ShellObject.FromParsingName でファイルの情報を取得し、Properties.System.Media.Duration で該当プロパティの値を取得します。 注意しなければならないのは、ファイルに再生時間(Duration)プロパティが無い場合は、Properties.System.Media.Duration がnull になります。 また、ファイルが破損していたりして再生時間が記録されていない場合は、Properties.System.Media.Duration.ValueAsObject がnull になります。

JR回数券と定期券の併用方法について

たまに使用する電車の乗車回数券ですが、定期券との併用方法をよく忘れるのでメモ

この記事で紹介する内容はJR西日本大阪環状線JR神戸線)でのみ使用可能であることを確認しています。
全ての線区・区間が同じ仕組みかどうかはわかりませんのでご注意ください。
※この記事は2017年7月時点のものです。

回数券はJRの券売機で購入することができる乗車券です。
詳細については以下のページを確認してください。

faq.jr-odekake.net

通常、定期券は以下の様に複数の駅間で使用していると思います。
f:id:iyemon018:20170720165411p:plain


ここで例えばB駅で乗り換えてD駅まで定期的に移動することになった場合、回数券を使用すると少し交通費を節約することができます。
f:id:iyemon018:20170720165646p:plain

イメージとしてはこんなところでしょうか。
この②の区間の回数券を購入し、通常使用している①区間の定期券と合わせて使用することが可能です。
ただし、行き(上記A駅からD駅へのルート)と帰り(上記D駅からA駅へのルート)で手順が異なるので注意してください。

■行き

1.A駅で定期券を使って乗車する。
2.D駅まで乗車する。
3.D駅の精算機でカード挿入口に"定期券"→"回数券"の順番に挿入する。
  この時、定期券にチャージ済みであってもこの方法を使用することはできます。
  ただし、支払い不要のメッセージが表示されるので素早く回数券を投入してください。
4.出場証が発行されるので通常の切符と同じように使用する。

■帰り

1.D駅で回数券を使用して乗車する。
2.A駅まで乗車する。
3.A駅の精算機でカード挿入口に"回数券"→"定期券"の順番に挿入する。
4.出場性が発行されるので通常の切符と同じように使用する。

乗車するときと生産する際の手順が異なります。
特に乗車する際は手順を間違えると回数券で支払いすることができなくなるので注意してください。