コグノスケ


2017年 7月 1日

飲みすぎると、音が高くなる

大学生ぐらいの時から不思議だったのですが、飲み過ぎた日、もしくは次の日に「音が高く」聞こえる人居ませんか?

普段から聞き慣れた曲って頭の中で再生できるじゃないですか。あれをやりながら、実際にその曲を聴くと、普段は合っているのに、酒飲みすぎた日は実際の曲の方が音が高いんです。

頭の中で再生できるほど聞き込んでなくても、曲の始まりくらいは覚えてますよね。さあ、この音が鳴るぞ〜と思っている音と、実際に聞こえてくる音がズレていて、高く感じるんです。

そういえば、環境音とか雑音も普段より高く聞こえているはずですが、気になりませんね。私が音を覚えられないためか、高いのか合っているのか良くわからないからでしょうか……?

耳が間違ってるのか、記憶が間違っているのか

聞こえる音が高くなると書きましたが「聞こえる音が高くなる」ではなく「記憶していた音が低くなる」可能性もあります。

確かめるには、酔って音が変に聞こえている時に何かの音を覚えて、素面の時に聞いてみる方法があります。音が高く聞こえたら酔うと耳がおかしくなって記憶は正しく、同じ音に聞こえたら耳は正しくて酔うと記憶がおかしくなる、というように判断できるはずです。

しかし、酔ってるときにそんなことしたら絶対気持ち悪くなるので、確かめたくありません……。あと両方おかしくなる場合は判別できません。

飲み会で思い出す度に色んな人に聞いてますが、今のところ同意してくれる人が居らず。一体、何なんでしょう?何かの病気?

編集者: すずき(更新: 2017年 7月 2日 14:42)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2017年 7月 2日

いまさら Cocos2d-x を触ってみる その 2

先日(2017年 6月30日の日記参照)の続きです。Cocos2d-x がビルドできたら、開発環境のセットアップをします。といっても setup.py を実行して、質問に答えるだけです。

Cocos2d-x 環境設定
$ cd cocos2d-x

$ ./setup.py 

Setting up cocos2d-x...
->Check environment variable COCOS_CONSOLE_ROOT
  ->Search for environment variable COCOS_CONSOLE_ROOT...
    ->COCOS_CONSOLE_ROOT not found

  -> Add COCOS_CONSOLE_ROOT environment variable...
    ->Added COCOS_CONSOLE_ROOT=/home/katsuhiro/usr/src/cocos2d-x/tools/cocos2d-console/bin
...

->Check environment variable NDK_ROOT
  ->Search for environment variable NDK_ROOT...
    ->NDK_ROOT not found

  ->Search for command ndk-build in system...
    ->Command ndk-build not found

  ->Please enter the path of NDK_ROOT (or press Enter to skip): ★★Enterを押す★★
...

->Check environment variable ANDROID_SDK_ROOT
  ->Search for environment variable ANDROID_SDK_ROOT...
    ->ANDROID_SDK_ROOT not found

  ->Search for command android in system...
    ->Command android not found

  ->Please enter the path of ANDROID_SDK_ROOT (or press Enter to skip): ★★Enterを押す★★
...

Please execute command: "source /home/katsuhiro/.bashrc" to make added system variables take effect

最初に Android NDK の場所を聞かれ、次に Android SDK の場所を聞かれます。もし Android 向けにビルドしないのであれば、Enter を連打して無視しても構いません。私はスマホでもゲームを動かしてみたかったのでインストールしました。

Android SDK と NDK

Android SDK のコマンドラインツールは Android Studio のダウンロードサイトの一番下にある "Get just the command line tools" にあります。Android NDK は Android NDK のダウンロードサイトにあります。

SDK と NDK はどこに配置しても良いみたいです。私は ~/usr/lib/ の下に放り込んでおきました。

Android SDK と NDK のインストール
$ cd ~/usr/lib
$ unzip android-ndk-r15b-linux-x86_64.zip
...省略...
$ ln -s android-ndk-r15b android-ndk

$ cd ~/usr/lib
$ mkdir android-sdk
$ cd android-sdk
$ unzip sdk-tools-linux-3859397.zip
...省略...


$ cd ~/usr/lib
$ tree -L 2
.
├── android-ndk -> android-ndk-r15b
├── android-ndk-r15b
│   ├── CHANGELOG.md
│   ├── README.md
│   ├── build
│   ├── meta
│   ├── ndk-build
│   ├── ndk-depends
│   ├── ndk-gdb
│   ├── ndk-stack
│   ├── ndk-which
│   ├── platforms
│   ├── prebuilt
│   ├── python-packages
│   ├── shader-tools
│   ├── simpleperf
│   ├── source.properties
│   ├── sources
└── android-sdk
    └── tools

それと SDK や NDK のバージョン名が変わるたびにセットアップし直すのは面倒だったので、NDK はシンボリックリンクを張りました。手抜きです……。

Cocos2d-x 環境設定、やり直し
$ cd cocos2d-x

$ ./setup.py 

Setting up cocos2d-x...
->Check environment variable COCOS_CONSOLE_ROOT
  ->Search for environment variable COCOS_CONSOLE_ROOT...
    ->COCOS_CONSOLE_ROOT is found : /home/katsuhiro/usr/src/cocos2d-x/tools/cocos2d-console/bin
...

->Check environment variable NDK_ROOT
  ->Search for environment variable NDK_ROOT...
    ->NDK_ROOT not found

  ->Search for command ndk-build in system...
    ->Command ndk-build not found

  ->Please enter the path of NDK_ROOT (or press Enter to skip): /home/katsuhiro/usr/lib/android-ndk
  -> Add NDK_ROOT environment variable...
    ->Added NDK_ROOT=/home/katsuhiro/usr/lib/android-ndk

->Check environment variable ANDROID_SDK_ROOT
  ->Search for environment variable ANDROID_SDK_ROOT...
    ->ANDROID_SDK_ROOT not found

  ->Search for command android in system...
    ->Command android not found

  ->Please enter the path of ANDROID_SDK_ROOT (or press Enter to skip): /home/katsuhiro/usr/lib/android-sdk
  -> Add ANDROID_SDK_ROOT environment variable...
    ->Added ANDROID_SDK_ROOT=/home/katsuhiro/usr/lib/android-sdk
...

Please execute command: "source /home/katsuhiro/.bashrc" to make added system variables take effect

環境設定はうまく行ったようです。最後に出ているメッセージの言う通り source ~/.bashrc を実行すれば、cocos というコマンドが実行できるようになっているはずです。

ゲームのプロジェクトを生成する

Cocos2d-x の開発では cocos コマンドを使うそうです。まずは cocos new でゲームのプロジェクト(テンプレート?)を生成します。

プロジェクト名は mygame1 で、パッケージ名は net.katsuster.mygame1(-p net.katsuster.mygame1)、C++ で開発します(-l cpp)。プロジェクトをディレクトリ mygame に置いてもらいます(-d mygame)。何も指定しないと MyCppGame というディレクトリ名になりますが、リネームしても別に問題はありません。

新規プロジェクトを生成
$ mkdir ~/cocos
$ cd ~/cocos

$ cocos new mygame1 -p net.katsuster.mygame1 -l cpp -d mygame
> Copy template into /home/katsuhiro/cocos/mygame/mygame1
> Copying Cocos2d-x files...
> Rename project name from 'HelloCpp' to 'mygame1'
> Replace the project name from 'HelloCpp' to 'mygame1'
> Replace the project package name from 'org.cocos2dx.hellocpp' to 'net.katsuster.mygame1'
> Replace the Mac bundle id from 'org.cocos2dx.hellocpp' to 'net.katsuster.mygame1'
> Replace the iOS bundle id from 'org.cocos2dx.hellocpp' to 'net.katsuster.mygame1'

$ ls mygame
mygame1

$ ls mygame/mygame1/
CMakeLists.txt  cocos2d              proj.ios_mac  proj.win10
Classes         proj.android         proj.linux    proj.win32
Resources       proj.android-studio  proj.tizen

ディレクトリを覗くと、訳のわからないファイルが大量に生成されていて面食らいますが、とりあえず何も気にせず、ビルド&実行してみます。

ビルド対象は先程生成した mygame1(-s mygame/mygame1)で、ターゲットは Linux 向け(-p linux)です。初回のビルドはかなり時間がかかりますが、二回目以降は変更した部分だけビルドするため、非常に早いです。

新規プロジェクトをビルド、実行失敗
$ cocos compile -s mygame/mygame1/ -p linux

Building mode: debug
running: 'cmake -DCMAKE_BUILD_TYPE=Debug -DDEBUG_MODE=ON ..'

-- The C compiler identification is GNU 6.3.0 

...(初回だけかなり時間掛かります)...

[100%] Building CXX object CMakeFiles/MyGame.dir/Classes/HelloWorldScene.cpp.o
[100%] Building CXX object CMakeFiles/MyGame.dir/Classes/AppDelegate.cpp.o
[100%] Linking CXX executable bin/MyGame
[100%] Built target MyGame
Build succeed.


$ cocos run -s mygame/mygame1/ -p linux
Building mode: debug
running: 'cmake -DCMAKE_BUILD_TYPE=Debug -DDEBUG_MODE=ON ..'

...

[100%] Built target MyGame
Build succeed.
Deploying mode: debug
Starting application.
running: '/home/katsuhiro/cocos/mygame/mygame1/bin/debug/linux/MyGame'

/home/katsuhiro/cocos/mygame/mygame1/bin/debug/linux/MyGame: error while loading shared libraries: libfmod.so.6: cannot open shared object file: No such file or directory
Error running command, return code: 127.

上記ではビルドだけするため、あえて cocos compile を使いましたが、実は cocos run がビルドと実行を同時にやってくれるので、cocos compile は使う必要がありません。

それは良いとして cocos run が失敗してしまいました。libfmod.so.6 が無いとか言っています。このライブラリは cocos2d-x/external/linux-specific/fmod/prebuilt/64-bit/libfmod.so に置いてあるようなのですが、名前がちょっと違っているので、libfmod.so.6 という名前のシンボリックリンクを作ってあげて、ライブラリのパスも通してあげると動きます。

新規プロジェクトを実行
$ cd ~/usr/src/cocos2d-x
$ cd external/linux-specific/fmod/prebuilt/64-bit
$ ln -s libfmod.so libfmod.so.6

$ echo 'export LD_LIBRARY_PATH=$COCOS_X_ROOT/cocos2d-x/external/linux-specific/fmod/prebuilt/64-bit' >> ~/.bashrc
$ source ~/.bashrc

$ cd ~/cocos
$ cocos run -s mygame/mygame1/ -p linux
...
Build succeed.
Deploying mode: debug
Starting application.
running: '/home/katsuhiro/cocos/mygame/mygame1/bin/debug/linux/MyGame'

Ready for GLSL
Ready for OpenGL 2.0

        gl.supports_OES_packed_depth_stencil: false
        gl.supports_OES_depth24: false
        gl.supports_OES_map_buffer: false
        gl.supports_vertex_array_object: true
        gl.renderer: Gallium 0.4 on llvmpipe (LLVM 3.9, 128 bits)
        gl.version: 3.0 Mesa 13.0.6
        cocos2d.x.compiled_with_gl_state_cache: true
        cocos2d.x.version: cocos2d-x-3.15.1
        gl.supports_S3TC: true
        cocos2d.x.build_type: DEBUG
        cocos2d.x.compiled_with_profiler: false
        gl.vendor: VMware, Inc.
        gl.max_texture_units: 96
        gl.max_texture_size: 8192
        gl.supports_ATITC: false
        gl.supports_ETC1: false
        gl.supports_PVRTC: false
        gl.supports_NPOT: true
        gl.supports_BGRA8888: false
        gl.supports_discard_framebuffer: false



libpng warning: iCCP: known incorrect sRGB profile
cocos2d: QuadCommand: resizing index size from [-1] to [2560]

下記のように宇宙人のような顔が描いてある画面が出れば成功です。


Cocos2d-x Hello World

そういえば何も考えず TigerVNC 上で実行していますが、難無く 60fps 出て驚きました。画面サイズが小さくて、動きがほとんど無いから軽いだけかも知れませんけど、便利だし問題起きるまで VNC 越しで開発してみようかなあ。

ひとまず Linux 向けには作り始めることができそうです。今回はここまで。

編集者: すずき(更新: 2017年 7月 3日 01:23)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2017年 7月 3日

仮想アドレスから物理アドレスへ

ちょっと用事があって、ユーザプロセスの仮想アドレスから、物理アドレスへの変換を行うプログラムを作りました。名前は v2p(virt2phys)です。何の捻りもありません。ソースコードは GitHub に置いています。

やっていることは /proc/pid/pagemap を読んで、わかりやすい形式で表示しているだけです。言葉で説明するより動いている姿の方がわかりやすいと思います。

実験に使った環境は Debian GNU/Linux Testing amd64 版です。別に Debian じゃなくても最近の Linux なら動くと思います。

このツールの実行には、プロセス ID と仮想アドレスが必要です。まず解析に使うプロセスを作って、プロセス ID を調べます。

cat を実行&中断
$ cat
[Press Ctrl+Z]
[1]+  Stopped                 cat

$ ps
  PID TTY          TIME CMD
 2148 pts/4    00:00:00 bash
14010 pts/4    00:00:00 cat  ★★cat の PID を覚えておく★★
14015 pts/4    00:00:00 ps

プロセス ID がわかったら、物理アドレスに変換したい仮想アドレスを決めます。ここでは例としてヒープ領域の先頭アドレスを変換しましょう。

cat のヒープ領域の仮想アドレス
$ cat /proc/14010/maps
55ff09a4f000-55ff09a57000 r-xp 00000000 08:11 5505114                    /bin/cat
55ff09c56000-55ff09c57000 r--p 00007000 08:11 5505114                    /bin/cat
55ff09c57000-55ff09c58000 rw-p 00008000 08:11 5505114                    /bin/cat
55ff0b2cb000-55ff0b2ec000 rw-p 00000000 00:00 0                          [heap]    ★★これを使う★★
7fdbeb6a3000-7fdbeb838000 r-xp 00000000 08:11 4980859                    /lib/x86_64-linux-gnu/libc-2.24.so
7fdbeb838000-7fdbeba38000 ---p 00195000 08:11 4980859                    /lib/x86_64-linux-gnu/libc-2.24.so
...(snip)...
7ffdde79c000-7ffdde7be000 rw-p 00000000 00:00 0                          [stack]
7ffdde7fb000-7ffdde7fd000 r--p 00000000 00:00 0                          [vvar]
7ffdde7fd000-7ffdde7ff000 r-xp 00000000 00:00 0                          [vdso]

プロセス ID と仮想アドレスがわかったので、物理アドレスに変換します。

仮想アドレスから物理アドレスへ
$ sudo ./src/v2p 14010 0x55ff0b2cb000 0x4000
pid: 14010:
 virt:0x55ff0b2cb000, phys:0x73a42b000
 virt:0x55ff0b2cc000, phys:(not present)
 virt:0x55ff0b2cd000, phys:(not present)
 virt:0x55ff0b2ce000, phys:(not present)

変換できました。特権のない状態で実行すると全て 0x00000000 になってしまいますので、お気をつけください。

表示の意味は特に何の捻りもなく、物理アドレスをそのまま示しています。ちなみに (not present) と表示される場合は、まだカーネルからページが割り当てられておらず、仮想アドレスに対応する物理アドレスが存在しないことを意味しています。

デマンドページング

これだけだと GitHub に書いた Readme そのものだし、へぇー…って感じがするだけで面白くないので、cat に gdb でアタッチしてヒープ領域を触ったらどうなるか見てみます。

gdb でアタッチして 3番目と 5番目のページを read する
$ sudo ./src/v2p 14010 0x55ff0b2cb000 0x6000
pid: 14010:
 virt:0x55ff0b2cb000, phys:0x73a42b000
 virt:0x55ff0b2cc000, phys:(not present)
 virt:0x55ff0b2cd000, phys:(not present) ★これを読む★
 virt:0x55ff0b2ce000, phys:(not present)
 virt:0x55ff0b2cf000, phys:(not present) ★これを読む★
 virt:0x55ff0b2d0000, phys:(not present)


$ gdb -p 14010
GNU gdb (Debian 7.12-6) 7.12.0.20161007-git
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
...
0x00007fdbeb77e690 in __read_nocancel ()
    at ../sysdeps/unix/syscall-template.S:84
84      ../sysdeps/unix/syscall-template.S: そのようなファイルやディレクトリはありません.

(gdb) x/4x 0x55ff0b2cd000
0x55ff0b2cd000: 0x00000000      0x00000000      0x00000000      0x00000000

(gdb) x/4x 0x55ff0b2cf000
0x55ff0b2cf000: 0x00000000      0x00000000      0x00000000      0x00000000


$ sudo ./src/v2p 14010 0x55ff0b2cb000 0x4000
pid: 14010:
 virt:0x55ff0b2cb000, phys:0x73a42b000
 virt:0x55ff0b2cc000, phys:(not present)
 virt:0x55ff0b2cd000, phys:0x1cb695000 ★ゼロページが割り当たる★
 virt:0x55ff0b2ce000, phys:(not present)
 virt:0x55ff0b2cf000, phys:0x1cb695000 ★ゼロページが割り当たる★
 virt:0x55ff0b2d0000, phys:(not present)

試しに 3番目と 5番目の領域からデータを読み出してみました、どちらも 0 データが見えます。読み出したあとは 0x1cb695000(数字は環境によって違います)という同じアドレスが割り当たりました。このアドレスは全て 0 で埋まっている特殊なページを指していて、読み出したときにとにかく 0 データを返せば良い領域に使われるらしいです。

じゃあ今度は書いてみたらどうなるでしょう?

gdb でアタッチして 2番目と 3番目のページを read する
$ sudo ./src/v2p 14010 0x55ff0b2cb000 0x6000
pid: 14010:
 virt:0x55ff0b2cb000, phys:0x73a42b000
 virt:0x55ff0b2cc000, phys:(not present) ★これに書く★
 virt:0x55ff0b2cd000, phys:0x1cb695000   ★これに書く★
 virt:0x55ff0b2ce000, phys:(not present)
 virt:0x55ff0b2cf000, phys:0x1cb695000
 virt:0x55ff0b2d0000, phys:(not present)


(gdb) set *((long *)(0x55ff0b2cc000))=0x89abcdef

(gdb) x/4x 0x55ff0b2cc000
0x55ff0b2cc000: 0x89abcdef      0x00000000      0x00000000      0x00000000

(gdb) set *((long *)(0x55ff0b2cd000))=0x12345678

(gdb) x/4x 0x55ff0b2cd000
0x55ff0b2cd000: 0x12345678      0x00000000      0x00000000      0x00000000


$ sudo ./src/v2p 14010 0x55ff0b2cb000 0x4000
pid: 14010:
 virt:0x55ff0b2cb000, phys:0x73a42b000
 virt:0x55ff0b2cc000, phys:0x73c76a000 ★ページが割り当たる★
 virt:0x55ff0b2cd000, phys:0x72edd0000 ★ゼロページが外され、別のページが割り当たる★
 virt:0x55ff0b2ce000, phys:(not present)
 virt:0x55ff0b2cf000, phys:0x1cb695000
 virt:0x55ff0b2d0000, phys:(not present)

2番目の (not present) な領域にも書けますし、3番目のゼロページが割り当たっている領域にも書けます。読み出してみても、ちゃんと書けていることがわかります。

書き込んだあとの仮想アドレスと物理アドレスの対応を見ると、2番目は read した時とは違ってゼロページではなさそうなアドレスが割当たります。3番目はゼロページが外され、別のページが割り当てられます。

不思議に見えるかも知れませんが、ゼロページは 0 データを返す専門なので、書き込みができません、というかカーネルが書き込みを許しません。ゼロページに書き込もうとした場合はゼロページを外して別のページを割り当て、以降はそのページを使って下さい、という仕組みになっています。

編集者: すずき(更新: 2017年 7月 4日 00:29)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



こんてんつ

open/close wiki
open/close Java API

過去の日記

open/close 2002年
open/close 2003年
open/close 2004年
open/close 2005年
open/close 2006年
open/close 2007年
open/close 2008年
open/close 2009年
open/close 2010年
open/close 2011年
open/close 2012年
open/close 2013年
open/close 2014年
open/close 2015年
open/close 2016年
open/close 2017年
open/close 2018年
open/close 2019年
open/close 2020年
open/close 2021年
open/close 2022年
open/close 2023年
open/close 過去日記について

その他の情報

open/close アクセス統計
open/close サーバ一覧
open/close サイトの情報