2010年12月19日日曜日

Bezier曲線

OpenGLで曲面を描画する方法について調べている。
その中でベジエ曲線とかB-splite曲線とかいろいろ出てきた。

文章や図を眺めてるだけだけじゃイマイチ理解が深まらないので、Procceing上でベジエ曲線描画するプログラムを自力実装してみた(注:Processingにはベジエ曲線を描画するための関数、bezier()があるので純粋に描画したいだけならそれ使った方が早いです)。


int w = 500;
int h = 500;

void setup(){
smooth();
noStroke();
fill(200,0,0,200);
size(w,h);
float[][] pArray ={{50.,200.},
{200.,100.},
{300.,400.},
{450.,200.}};
fill(0,200,0,200);
Bezier(pArray);


fill(200,0,0,200);
for(int i = 0;i < pArray.length;i++){
ellipse(pArray[i][0],pArray[i][1],10,10);
}
}

void draw(){
}

int combination(int n,int k){
int c = 0;

c = factorial(n) / (factorial(k) * factorial(n - k));

return c;
}

int factorial(int n){

if(n == 0){
return 1;
}

int f = 0;

if(n == 1){
return n;
}
else{
f = n * factorial(n - 1);
}
return f;
}

float Berstein(int i,int N,float t){
float b = 0;
b = combination(N,i) * pow((1 - t),(N - i)) * pow(t,i);
return b;
}

void Bezier(float[][] pArray){
final int numT = 1000;
final int x = 0;
final int y = 1;

for(int ti = 0;ti <= numT;ti++){
float t = ti / float(numT);
float px = 0;
float py = 0;
for(int i = 0;i < pArray.length;i++){
float b = Berstein(i,pArray.length - 1,t);
px += b * pArray[i][x];
py += b * pArray[i][y];
}
ellipse(px,py,10,10);
}
}


出力結果はこんな感じ。

2010年12月15日水曜日

OpenGLのキーボード入力

OpenGL触ってて、色々と引っかかったのでメモ。

・OpenGLで矢印とかファンクションキーから入力を受け付けたい場合は、glutSpecialFunc()に特殊キーのコールバック関数を設定する必要がある(C++の場合。Pythonの場合は特殊キーがどうとか考えなくてOK←追記:PyQtでOpenGLウィジェットを用いる場合の話です。OpenGL単体で使う場合は必要)。

※こんな感じ

void specialKeyFunc(unsigned char key,int x,int y){
if(key == GLUT_KEY_LEFT){
//process
}
else if(key == GLUT_KEY_RIGHT) {
//process
}
}

glutSpecialFunc(specialKeyFunc);


・文字を描画する際にはglutBitmapCharacter()を利用する(ココとかココを参考に)。

2010年12月13日月曜日

続OpenCV(光学迷彩的な何か

引き続きOpenCV。
光学迷彩的な何かを作ってみた。

やってることは至極単純で、事前に撮影した室内の画像とwebカムからキャプチャした画像の差分を計算しているだけ。


↑こんなん。左上が処理後、右上がキャプチャ画像、左下がもとの背景画像。
デコ部分の処理が甘く浮き上がってしまっている…。


それにしても、1000円かそこらのwebカムと無料のソフトウェアライブラリでここまで遊べるとは…。
引き続きいろいろ試してみたい所存でございます。

2010年12月12日日曜日

OpenCVが楽しすぎる件について

C++の勉強がてらOpenCVを触っているんだけど、これがかなり楽しい。

とりあえず、Webカムからリアルタイムに画像取得→画像から顔認識して顔部分の色を変化させる、くらいまでは簡単に出来た。




※左がカメラキャプチャした元画像、右が顔認識した部分の色を変化させたもの


一応下に使用したC++のソースを載せておく。


#include <cv.h>
#include <highgui.h>
#include <ctype.h>

int main (int argc, char **argv)
{
CvCapture *capture = 0;
IplImage *frame = 0;
IplImage *out = 0;
double w = 320, h = 240;
int c;

if (argc == 1 || (argc == 2 && strlen (argv[1]) == 1 && isdigit (argv[1][0])))
capture = cvCreateCameraCapture (argc == 2 ? argv[1][0] - '0' : 0);

cvSetCaptureProperty (capture, CV_CAP_PROP_FRAME_WIDTH, w);
cvSetCaptureProperty (capture, CV_CAP_PROP_FRAME_HEIGHT, h);

CvHaarClassifierCascade* cascade = cvLoadHaarClassifierCascade( "C:/OpenCV2.0/data/haarcascades/haarcascade_frontalface_default.xml",cvSize(1,1));
CvMemStorage* storage = cvCreateMemStorage(0);

cvNamedWindow ("Capture", CV_WINDOW_AUTOSIZE);
cvNamedWindow("Face detection", CV_WINDOW_AUTOSIZE);
while (1) {
frame = cvQueryFrame (capture);
cvShowImage ("Capture", frame);

out = frame;

CvSeq* objects = cvHaarDetectObjects(
frame,
cascade,
storage,
1.1,
2,
0,
cvSize(30,30));

for(int i = 0;i < (objects ? objects->total : 0);i++){
CvRect* r = (CvRect*) cvGetSeqElem(objects,i);
cvSetImageROI(out,cvRect(r->x,r->y,r->width,r->height));
cvAddS(out,cvScalar(200),out);
cvResetImageROI(out);
}

cvShowImage("Face detection",out);

c = cvWaitKey (2);
if (c == '\x1b')
break;
}

cvReleaseCapture (&capture);
cvDestroyWindow ("Capture");
cvDestroyWindow ("Face detection");

return 0;
}



※おまけ


お約束。

EclipseとCDTとPythonとOpenCVとわた(ry

今日も引き続きEclipseの環境構築。

OpenCVなぞをインストールしていた。

手順に関してはココを参考にしておけば間違いない。

とにかく問題になったのはOpenCVの最新バージョン2.2をインストールしてしまったこと。
上記サイトでは2.0をインストールしていて、そのとおりにやってみると確かに動く。

これが2.2をインストールしてしまうと、CDTでもPythonでも動かなかった(少なくとも自分の使っているマシンでは)…。

ソフトウェアモジュールはできるだけ安定して動くバージョンをインストールしよう、というお話。

2010年12月11日土曜日

EclipseとCDTとOpenGLと私

Eclipse+CDT+OpenGLメモ

・glutの設定はココに書いてある通り行うべし
・OpenGLプログラムを作成する際、描画関数内で頂点情報を指定したあと、swapBufferes()を忘れずに記述すること
※2010/12/12/追記:swapBuffers()は無くてもOK

2010年11月19日金曜日

ProcessingでAndroidアプリ開発

最近Processingにハマっている。

ProcessingはMITメディアラボで開発されたプログラミング言語。
メディアアートやインフォデザインなんかによく使われているらしい。

画像やインタラクションに強いため「動くモノ」、「触れるモノ」を簡単に作れるので触っててすごく楽しい。


そんなProcessingでAndroidアプリを作る方法を発見した。

…が、上記サイトの通りやってもうまく行かなかったので解決方法についてメモ。

とりあえずサイトの通りの手順だと

1.AndroidSDKをインスコ
2.Android互換バージョンのProcessingをココからゲッツ。解凍する。
3.Processingを立ち上げ、コーディング
4.コーディングし終わったら動作テスト
5.メニューバーの中にあるAndroid>Android Mode(もしくはCtrl+D)を選択。ファイルダイアログが出てくるのでAndroidSDKが保存してあるフォルダを選択する。

…ここで問題が発生した。
「Android core.zipがダウンロード出来ない」というエラーメッセージが出てきてうまくいかない。

ちょっと調べたところ、ココからファイルをダウンロードする部分がうまく動いていない様子。
上記ファイルを直接ダウンロード→Sketchフォルダに保存するとうまくいった。


…が、いざ実機にインストール、と思ったら自分が使っている端末のOSのバージョンがAndroid1.6で対応していなかった orz(エミュレータではキチンと動作しました)


まぁそれはいずれNexus Sを買ったときにでも(いつになることやら…)。


冒頭にも書きましたが、Processingはビジュアルやインタラクションに強く図形の描画、マウス、キー入力の取得が容易にできるプログラミング言語。
ということで、ゲームやデザイン系アプリのちょっとしたプロトタイプ開発に向いているんじゃないかな、と思います。

2010年10月23日土曜日

HT 03-Aの加速度センサ

HT 03-Aでプログラミングしていたときのこと。
EclipseのAndroid LogCat中に下記のような記述を発見。


10-23 14:55:42.172: DEBUG/SensorManager(4725): found sensor: AK8976A 3-axis Accelerometer, handle=0


"AK8976A"
「これはもしや、加速度センサの型番では?」
と思い、ググってみたら正解だったようで、旭化成の3軸加速度、電子コンパスICがヒットした。
データシートによるとサンプリング間隔は10~15msらしい。
つまり、SENSOR_DELAY_FASTESTで計測しても上記のサンプリング間隔より早く計測することは出来ない、ということ。

加速度センサ使ってアプリ作る人はこの点、ちょっと気を付けておいた方がいいかもです。

2010年10月12日火曜日

OEDEC2007の資料がかなり良さげ

音声処理について調べてる途中で、OEDEC2007のセッション資料を発見したのでメモ。
これが中々良さげ(以前Blogに掲載したAMDFの分かりやすい説明なんかも載っていた)。

音声処理以外にも映像やらデータ圧縮技術なんかについても掲載されているので非常に興味深い。
時間が出来たらじっくり読んどこう。

2010年10月4日月曜日

PythonWebめぐり

ウェーブレット変換の勉強中。
Web巡回して資料を探している最中にPythonでオシロ作ってるプロジェクトを発見した(一番上のヤツ)。

これは凄い…。
PyQtとかいうGUIモジュール使って作ってるらしい。

リッチなGUIをPythonで作りたいと思ってたからちょっと勉強してみたい。
これを参考にして今まで作ってきたアプリをゴージャス(爆)に改良することを目標にやってみるか。
ちょっと調べてみた感じここら辺が勉強用に丁度よさそう。

#肝心のウェーブレット変換も同じページに載ってたのでいじくってみよう。

2010年9月26日日曜日

Pythonで少数を分数に変換する関数作った

前の記事で書いたwavファイルの速度調整用にスクリプト書いたので載せておく。

少数を分数に変換するための関数。


def Euclidean(m,n):
if m < n:
m,n = n,m
if n == 0:
return m
elif m % n == 0:
return n
else:return Euclidean(n,m%n)

def deciToFrac(deci):
i = 0
while deci % 1 != 0:
deci = deci * 10
i += 1

numer,denomi = int(deci),int(10 ** i)

gcd = Euclidean(numer,denomi)

return numer / gcd,denomi / gcd



下の関数に少数を渡すと通分された分数に変換し、分子と分母を返す。
上の関数はユークリッドの互除法。
これを使って分子、分母を通分している。


使用結果はこんな感じ。



>>> deciToFrac(2.6)
(13, 5)
>>> deciToFrac(1.2)
(6, 5)

PyAudioで早送り再生とかディレイとか

PyAudioでwavファイルを早送り再生したりディレイで再生したりしてみた。

早送りやディレイは音楽の波形データを時間軸上で伸縮させることにより実現できる。
縮ませると早く、引き伸ばすとゆっくり再生できる。

すでに音楽データを数値の配列として扱うことが出来ているわけだから、データ間を補間したり逆にデータを間引くことによりこれらを実現することができる。

試しにコーディングしてみた。


def delay(inp,rate):
outp = []

for i in range(len(inp)):
for j in range(rate):
outp.append(inp[i])

return array(outp)

def fast(inp,rate):
outp = []

for i in range(len(inp) / rate):
outp.append(inp[i * rate])

return array(outp)



引数rateは何倍に遅くしたい(or早くしたい)かを決定するためのもの。

そのまま使うと整数倍でしか再生スピードを調整できないけど、二つを組み合わせると自在に変更可能(1.1倍再生ならfast(data,11)とdelay(data,10)の組み合わせ、とか)。

簡単なコードだけど試してみたら結構面白かった。
是非お試しあれ。

※追記:上の二つの関数を再生スピード変更関数として一元化、PyAudioでwav再生するプログラムを作ってみた。


from scipy import *
import pyaudio
import wave
import sys

def changePlaySpeed(inp,rate):
outp = []
for i in range(int(len(inp) / rate)):
outp.append(inp[int(i * float(rate))])
return array(outp)

chunk = 1024

wf = wave.open("hoge.wav", 'rb')

p = pyaudio.PyAudio()

# open stream
stream = p.open(format =
p.get_format_from_width(wf.getsampwidth()),
channels = wf.getnchannels(),
rate = wf.getframerate(),
output = True)

# read data
data = wf.readframes(chunk)

# play stream
while data != '':
stream.write(data)
data = wf.readframes(chunk)
data = frombuffer(data,dtype = "int16")
if data != '':
data = changePlaySpeed(data,1.8)
data = int16(data).tostring()


stream.close()
p.terminate()



changePlaySpeed()の2番目の引数で再生スピードを変更できます(2.0だったら2倍速、0.5だったら半分のスピード)。

ゆっくり再生すると変な音が混ざった感じに聞こえる。
あまりイクナイ。

再生している音源が悪いのかしら?
データの補完方法に問題があるような気もするなぁ。

とりあえず試してみました、くらいの感覚で。

2010年9月24日金曜日

グラフの対数表示とか研究室のイベントとか

今日は所属研究室の初回ゼミ&歓迎会でした。

ということで酔ってます。

今日の更新はいつにも増して内容が薄いです。

周波数特性グラフをデシベル表示にしてみました、というだけ。


こんな感じ。





前の記事に掲載した内容とほぼ変わらす。


変更点は各周波数に対するゲインを求める式を以下のように変えたのみ。



>>> 20 * log10(f[i] / fmax)



最近リアルタイム音声処理の本とか読み始めたのでそちらについても書きたいなー。

2010年9月22日水曜日

一からデジタルフィルタ設計、Pythonで実装してみる(その2)

デジタルフィルタを一から設計してPythonで実装しよう!(タイトルまんま)
という企画の続き。

残る作業は
・数式内の定数を決める
・差分方程式を元にコーディング

たったこれだけの簡単なお仕事。


まず、数式内の定数を定める。

これは一番初めに決めた「信号から1000Hz以下の周波数成分をブっこ抜く」、という部分とデジタルフィルタの伝達関数から求めていく。

まずデジタルフィルタの伝達関数Hd(z)から周波数特性を得るため、z=e^(j2πfT)とする。
そしてその関数を用いて周波数特性を求めグラフにしたものがこちら。





遮断周波数(振幅が最大値に比べて√2/2になる周波数)が1000Hz付近になるようなRとCになっている。
R=1000、C=0.2uで決定。


これを差分方程式に代入してIIRフィルタとしてコーディングしてみる。



#coding:utf-8

from pylab import *
from scipy import *

def LPF(array):
output = []

R = 1000.
C = 0.0000002
Ts = 1 / 50000.

for i in range(len(array)):
if i == 0:
output.append(1/(R*C)*Ts*array[0])
else:
output.append(1/(R*C)*Ts*array[i] + exp(-1/(R*C)*Ts)*output[i-1])

return output

Fs = 50000.
Ts = 1 / Fs
t = arange(0,1,Ts)
f = 500

s1 = sin(2 * pi * f * t)
s2 = sin(2 * pi * 2 * f * t)
s3 = sin(2 * pi * 5 * f * t)

plot(t[0:200],LPF(s1)[0:200])
plot(t[0:200],LPF(s2)[0:200])
plot(t[0:200],LPF(s3)[0:200])
xlabel("time(s)")
legend(("500Hz","1000Hz","2500Hz"))

show()



結果がコチラ。





周波数特性と比較してみるとその通りにフィルタリングされている。

実際に周波数特性を求めたり、フィルタを作って分かったこと。
それは、アナログのローパス→インパルス不変法というデジタルフィルタの作り方だと、良い特性を持つLPFが作れないということ。
遮断周波数を過ぎてもすぐに減衰しない。

ということで実用的なデジタルフィルタを構築するには他の方式も勉強しておく必要があるようだ。

Pythonでフィルタリングツール

昨日の続き。
Python&matplotlibで移動平均フィルタリングアプリを作ってみた。
…とは言っても、かなりやっつけ仕事。

一応形にはなったので、画像とソースを張っておく。



左側がフィルタリング前の波形、右側がフィルタリング後の波形。
左下のスライダーがノイズ成分の強度調整、右下のスライダーが移動平均フィルタの強度調整。


以下が、ソースコード。


#coding:utf-8

from pylab import *
from matplotlib.widgets import Slider, Button

#FIR filter
def FIR(array,FIRCoefficient):
output = []

for i in range(len(array)):
temp = 0
for j in range(len(FIRCoefficient)):
temp += array[i - j] * FIRCoefficient[j]
output.append(temp)

return output

#Time axis
t = arange(0.0,1.0,0.0001)
f = 10
s = []

#Noise cofficient
nc = 1

#Noisy sine wave
for i in range(len(t)):
s.append(sin(2 * pi * f * t[i]) + nc * randn())

ax = subplot(121)
l, = plot(t,s)
axis([0,1,-10,10])
subplots_adjust(left=0.25, bottom=0.25)
xlabel("time(s)")
ax.set_position([0.1,0.5,0.35,0.3],"original")


#Filtered wave
FIRCoefficient = []
FIRlength = 10
for i in range(FIRlength):
FIRCoefficient.append(1/ float(FIRlength))
s2 = FIR(s,FIRCoefficient)
ax2 = subplot(122)
m, = plot(t[:len(s2)],s2)
axis([0,1,-10,10])
ax2.set_position([0.55,0.5,0.35,0.3],"original")


#Noise controll
axcolor = 'lightgoldenrodyellow'
axnoise = axes([0.1,0.3,0.32,0.03], axisbg = axcolor)
snoise = Slider(axnoise,"Noise",0.0,10.0,valinit = 1)

def update(val):
global s
nc = snoise.val
s = []
for i in range(len(t)):
s.append(sin(2 * pi * f * t[i]) + nc * randn())
s = array(s)
l.set_ydata(s)
FIRCoefficient = []
for i in range(FIRlength):
FIRCoefficient.append(1/ float(FIRlength))
s2 = FIR(s,FIRCoefficient)
m.set_ydata(s2)
draw()
snoise.on_changed(update)


#Filter length controll
axfilter = axes([0.55,0.3,0.32,0.03], axisbg = axcolor)
sfilter = Slider(axfilter,"Filter",5,30,valinit = 10)

def filtering(val):
global FIRlength
FIRlength = int(sfilter.val)
FIRCoefficient = []
#Moving average filter
for i in range(FIRlength):
FIRCoefficient.append(1/ float(FIRlength))
s2 = FIR(s,FIRCoefficient)
m.set_ydata(s2)
draw()
sfilter.on_changed(filtering)

show()


昨日作ったアプリと早いところ統合したいなぁ。
でも、その前にどっちのアプリも個別にブラッシュアップしとかないと。

2010年9月21日火曜日

PyAudioとmatplotlibで録音アプリ作った

今日、Twitterのタイムライン上に「JavaScriptでペイントアプリ作る。一日で」というのを行っている人がいたので、自分も何か作りたくなった。

ということでmatplotlibやらPyAudioの勉強がてら簡単な録音アプリをPythonで作ってみた。

速攻でコーディングしたせいでソースの見栄えが非常に悪いので(あとまだまだ不完全なので…)、GUIのスクリーンショットだけ載せておく。






左上のラジオボタンでサンプリングレートを、グラフ下部のスライダーをいじくると録音時間を設定できる。
Saveボタンで録音した音声をwav形式で保存、Recordボタンを押すと録音開始、という非常にシンプル(芸がないとも言う)なもの。


時間があったら、再生ボタンとかエフェクターとかフィルタとか色々実装してみたい。

こういうアプリを作ってると、GUIを自由にデザインして実装できるようになりたいなぁ、としみじみ思う。
matplotlibも悪くないけどやっぱりウィジェットの配置とかデザインとか一から全部手掛けたい。

Ajax(javascript)とかHTML5とかweb周りの技術触っときたいなー。

※参考にしたサイト
[1]wavファイルの保存処理
http://www.s12600.net/psy/python/02-1.html
[2]matplotlibのGUI周り
http://matplotlib.sourceforge.net/examples/widgets/

2010年9月19日日曜日

一からデジタルフィルタ設計、Pythonで実装してみる(その1)

これまで、デジタルフィルタの構成イメージを掴むため実際にPythonで実装してみた。

けど、本格的にフィルタを構築する場合、しっかりとした設計が必要になる。

ということで、今日はデジタルフィルタの設計について。



まず、大まかな設計の流れについて。
信号からある特定の周波数成分だけ抽出(あるいは除去)したいというニーズがあるとして、デジタルフィルタを設計するときは以下の6ステップを踏む必要がある。


(1)抽出したい成分の周波数を特定する
 目的とする信号とノイズを区別するため。

(2)目的に合わせてフィルタの種類(ローパス、ハイパス、バンドパスetc)を選択する
 高周波のノイズ除去ならローパス、FMラジオの電波受信みたいに特定の狭い周波数帯域だけ欲しい場合はバンドパス、など。

(3)選択したフィルタをアナログフィルタで実現した場合の伝達関数を求める
 この段階で得られた数式はs領域のもの。

(4)(3)で求めた伝達関数をデジタルフィルタの伝達関数に変換
 s-Z変換を用いて離散時間領域のシステムに変換する。

(5)(4)で得た伝達関数から差分方程式を導出
 伝達関数を式変形した後、z逆変換して導出。

(6)差分方程式を実際にコーディング


こんな感じ。
今までにやってきたフィルタの実装は(6)にあたる(設計がいかに大変な作業なのかがよく分かる…)。



練習がてら、上の6ステップに基づいて「信号から1000Hz以下の周波数だけ取り出すフィルタ」というものを1から設計してみる。


(1)周波数の特定
 上の題目から、取り出したい信号成分は1000Hz以下のもの。それ以上はノイズであるという前提条件を立てる。

(2)フィルタの選択
 「1000Hz以下の周波数だけ」とのことなので、ローパスフィルタを選択する。

(3)伝達関数導出
 回路理論の教科書を引っ張り出してローパスフィルタのアナログ回路構成と回路方程式、そして伝達関数を調べてみる。





図下部の数式は、回路方程式を立てる→ラプラス変換→H(s)導出、という流れになっている。
これで伝達関数H(s)が手に入った。

(4)s-Z変換を行う。これにはいくつか方法があるんだけど今回は「インパルス不変法」を使ってみる。
インパルス不変法はその名の通り、アナログフィルタのインパルス応答の標本値を利用する変換方式。

詳細の説明はコチラにゆずるとして、変換の過程はこんな数式。




めでたく、デジタルフィルタの伝達関数Hd(z)が手に入った。

※ここではオーソドックスな方法である、という理由からインパルス不変法を使った。けど本当は、前に決定した部分を振り返りながら、慎重にs-Z変換手法を選択しなければいけない。各変換手法にはそれぞれ得手、不得手があるからだ。
今回はローパスフィルタを試しに実装しているけど、実はインパルス不変法ではハイパスフィルタやバンドパスフィルタは実現できない
ということで、今回はサクっと設計手法を決めているけど、実際の設計では1ステップずつしっかりと進めていく必要がある。当たり前の話ではあるけれど、非常に重要かつ忘れがち…。


(5)差分方程式導出
差分方程式を求めるために、デジタルフィルタの伝達関数を式変形の後、z逆変換する。
…というと難しそうに聞こえるけど簡単で、ちょこちょこっと式変形を行うだけ。





最後に出てきた数式の中のvi(k)がFIRフィルタで実装する部分、vo(k-1)がIIRフィルタで実装する部分となる。

ここまで来たらあと少し。
いくつかの定数の値を決め、コーディングするのみ。

長くなってしまったので続きはまた今度。

※続きはコチラ

2010年9月18日土曜日

PythonでIIRフィルタ

Pythonで信号処理シリーズ。
IIRフィルタ編。

ホントはscipyのsignalモジュールにFIRフィルタとかIIRフィルタを実現するためのクラスだかメソッドだかがあるので、それを使えばいいと言う話なのだけど。
キチンと仕組みを理解してフィルタを使う、プログラミングの勉強の一環として、個人的な趣味、などの理由からフィルタをPythonで実装してみようという趣旨。


前置きはこのあたりにして、本題。


前の記事にも書いたけどIIRフィルタは出力のフィードバックをそのシステム内部に含むデジタルフィルタ。

出力のフィードバックを含むというのは、プログラムの観点から言うと「フィルタ自身が過去の出力を保存しており、適宜それを使用する仕組みを持っている」ということを意味している。

これに対して、FIRフィルタは「過去の入力を保存しておき、それを適宜使用する」といったものだった。
このFIRフィルタにフィードバック機構を備え付けたものがIIRフィルタだ。
イメージとしては

FIRフィルタ+フィードバック機構=IIRフィルタ

といったような感じ(と、自分は捉えてる)。


それを踏まえてココを参考にIIRフィルタを以下のような形で設計してみた。





中央の加算器を挟んで左半分がFIR部分、右側がIIR部分となっている。
今回はIIRフィルタの影響のみを調べたいので、FIRフィルタの係数はインプットをそのまま出力する形となっている。


んでソースは下のようなものに。



#coding:utf-8

from scipy import *
from matplotlib.pylab import *

def IIR(array):
output = []

#係数格納行列
FIRCoefficient = [1,0,0]
IIRCoefficient = [0.7,0.2,0.1]

for i in range(0,len(array)):
temp = 0

for i in range(len(array)):
temp = 0
for j in range(len(FIRCoefficient)):
temp += array[i - j] * FIRCoefficient[j]
if len(output) > j:
temp += output[i - j - 2] * IIRCoefficient[j]

output.append(temp)

return output

Fs = 100.
t = arange(0,1,1/Fs)
f = 5

inp = []

#入力信号生成(正弦波+ノイズ)
for i in range(len(t)):
inp.append(sin(2 * pi * f * t[i]) + rand())

outp = IIR(inp)

plot(t,inp,"b")
plot(t,outp,"r")
xlabel("time(s)")
show()



出力結果がコチラ。





…発振してしまっている。

どうやらIIRフィルタの係数設定はかなり難しいみたい。
FIRフィルタのときは直感的に係数を決めて、目で見て分かるくらいの効果があるフィルタを作ることができた。
でもIIRの場合、そううまくはいかないようで。

係数の設定や構成など、設計段階で考慮しなければいけないことが多いみたいだ。
ということで次回はデジタルフィルタ設計の勉強をすることにするか。

PyAudioでピッチ検出

これまで、信号処理のアルゴリズムと音声入力を取り扱う方法について色々勉強してきた。
その中からPyAudioとAMDFアルゴリズムを組み合わせて、マイクから音声を拾って音程を探り当てる、ということをやってみた。

まず、マイクに向かって「ド」の音階を出すつもりで発声してみる。





拡大してみると





それらしい波形になっている。


これにAMDFをかけたものがコチラ。





おおよそ0.0078(s)のあたりにピークが来ている。
これが声の基本周期だと考えると周波数は、1 / 0.0078 ≒ 128 (Hz)となる。

このサイトによると低い「ド」の音は131(Hz)とのこと。
そんなに大きくハズレてはいない模様。

少しホッとした。


現時点では、録音してAMDF結果を表示するまでの流れでプログラムが終了してしまうので、これをリアルタイムで出来るようにしたい。

2010年9月17日金曜日

信号処理の勉強その2

引き続き信号処理の勉強。

デジタルフィルタについて調べていた。
以下ざっくりとしたまとめ。

(1)デジタルフィルタとは
・フィルタとは信号から特定の周波数成分を抜き出す、あるいは除去するためのモノ
・離散値を処理するフィルタをデジタルフィルタという
・デジタルフィルタには線形フィルタと非線形フィルタがある(現時点ではこういうくくりがある、というぐらいで留めておく)
・デジタルフィルタは3つの基本的な構成要素から成る
 ー遅延素子:1クロック分、信号成分を遅延させて出力する素子
 ー加算器:入力された信号成分を足し合わせて出力する素子
 ー乗算器:入力された信号成分を定数倍して出力する素子

(2)FIR(Finite Inpulse Responce)フィルタ
フィードバックループが無いデジタルフィルタ。
インパルス応答が有限個のパルスで表されるからFIRフィルタ(らしい)。

(3)IIR(Infinite Inpulse Responce)フィルタ
フィードバックループを持つデジタルフィルタ。
インパルス応答が無限に続くインパルス列になるのでIIRフィルタ(らしい)。

全部ココを参考にして2、3行にまとめてみた(ザックリしすぎな感は否めない)。


ということで毎度お馴染みPythonでFIRフィルタを実装してみる。

ざっくり下のような感じで設計。
四角が遅延素子、三角が乗算器(内側の数字が係数)、丸が加算器。




んで、コーディングした結果がこちら。



#coding:utf-8

from scipy import *
from matplotlib.pylab import *

#FIRフィルタ
def FIR(array):
output = []

for i in range(2,len(array)):
output.append(array[i] * 0.7 + array[i-1] * 0.2 + array[i-2] * 0.1)

return output

Fs = 100.
t = arange(0,1,1/Fs)
f = 5

inp = []

#入力信号生成(正弦波+ノイズ)
for i in range(len(t)):
inp.append(sin(2 * pi * f * t[i]) + rand())

outp = FIR(inp)

plot(t,inp,"b")
plot(t[2:len(t)],outp,"r")
xlabel("time(s)")
show()



出力結果がコレ。




青が入力信号で赤が入力をフィルタリングした信号。

少し分かりづらいけれど、よく見るとフィルタリングを行う前と後で波形のギザギザが少なくなっていることが分かる。これは高周波のノイズがフィルタによって除去されたことを意味する。
ごくごく簡単なローパスフィルタ(低周波数の信号のみ通すフィルタ)が完成した。

ということで遅延素子を用いるとローパスフィルタを作ることが出来る、ということがこれで分かった。

2010年9月16日木曜日

キーボードチェッカー

「ハッカープログラミング大全」という本を読んでいる。

その中の「キーストロークを監視する」プログラムが面白かったのでPythonで実装してみた。
ということで公開…したかったけど、ちょっと思いとどまった。
簡単に悪用されてしまいそうなので、止めておく。
実際にパスワードを盗みだす手段として一般的なものとなっているみたい。
参考:「キーロガーの悪用が急増中」(2007年)


ただせっかく作ったのに何も残さないのは勿体無いので、参考までにPythonでキーロガーをプログラミングする上で大事そうなポイント2つ、書き出してみる。


・キーボードチェックのループは0.02s間隔で回すと実際のキーストロークと(多分)同じ間隔になる
・キーの状態は4種類(カッコの中はキーチェック関数の戻り値)
 ー押した瞬間(-32767)
 ー押しっぱなしの状態(-32768)
 ー離した瞬間(1)
 ー押されていない状態(0)


この技術、悪用するというのは問題外なので考えないとしても、色々面白い使い道がありそう。

最近、キーストロークのクセで個人認証を行う技術が発表されていたし、単純にログを取ってみるだけでも何か見えてきそうな気がする。

それ以外に思いつくものとしては、
ゲームをプレイしている人のキーボードのデータのログを取って初心者がそれを参考にするとか。
あるいはソースコードや文章のバックアップ手段として使うとか(復元がかなり面倒臭そうだけど)。
あとはキーストロークのクセを見ぬいて、「ここを改善するともっとキータッチが早くなりますよ」とか教えてくれるアプリとか。

1、3番目は難しそうだけど2番目くらいなら出回っててもおかしくないんじゃないかと。

2010年9月15日水曜日

AMDF

AMDF(Average Magnitude Deference function)を用いたピッチ検出を試してみましたよ、というお話。

AMDFは自己相関、相互相関関数のようにピッチ検出に用いられるアルゴリズムのひとつ。

(※2010/10/12追記:OEDEC2007のプレゼン資料にAMDFの分かりやすい説明が載ってます)

ココとかココ(こちらはIEEEの認証が必要)を参考にAMDFをPythonで実装してみた。


def AMDF(array,frameLength):
amdf = []
length = len(array)
for i in range(frameLength):
temp = 0
for j in range(length):
temp += abs(array[j] - array[j - i])
amdf.append(temp / length)
return amdf



この関数が正しく動作するか確認するため、下のような波形を用意する。



周波数100Hzの方形波にノイズを加えたもの。


この波形にAMDFを適用して計算した結果がこちら。



0.01sに最小値のピークが出ている。
相互相関関数と違って、AMDFでは最小値となる点が周期性を表していることが分かる。

2010年9月14日火曜日

信号処理の勉強

SciPyも無事導入出来たということで、信号処理を勉強し始めた。
ということで調べたことをメモ。

・自己相関関数
時間領域において波形の周期性を調べる際に用いられる数学的手続き。
その波形自信の畳み込み積分を計算することによって求められる。
音声のピッチ検出などに応用されている。

・相互相関関数
2つの波形の類似性を調べるための数学的手続き。
自己相関関数と同様ピッチ検出などに応用されている。
2つの波形の畳み込み積分を計算することによって求められる。

どちらもピッチ検出に用いられているけれど、相互相関を使った方が自己相関を使うよりも計算負荷が低くいのでより良いとのこと。

毎度お馴染みPythonだったら、2つともnumpy.correlate()で計算可能。

ただし、自己相関関数を求める場合は下記のようにmodeに"same"を指定する必要あり。


>>> correlate(signal,signal,"same")


ただ使うだけじゃ面白くないので相互相関関数を自分で実装してみた。
CCFは(Cross Correlation Function:相互相関関数)の略。

def CCF(array1,array2):

if len(array1) < len(array2):
array1,array2 = array2,array1

ccf = []

for i in range(len(array1) - len(array2)):
temp = 0
for j in range(len(array2)):
temp += array2[j] * array1[j - i]
ccf.append(temp / len(array2))

return ccf


この関数を用いて10Hzの正弦波(サンプリング周波数1000Hz)と、その正弦波の先頭から1周期分の波形の相互相関を求めてみる。



青が元の正弦波、赤が正弦波の先頭1周期、緑がそれら二つの波形の相互相関。

相互相関の値が0,100,200…と100の倍数で最大値をとっている。

これはつまり、この正弦波が100ms(10Hz)の周期の波形であること示している。
…ということでキチンと計算できているようだ。

SciPyのsignalモジュール

オーディオ入力にフィルタをかける必要が出てきたので、SciPyをインストールしてみた。

で、早速信号処理用モジュールscipy.signalをインポートしてみると…エラーダイアログが出てくるのみ。
IDLEがリスタートしてしまって、インポート失敗している。

自分がインストールしたバージョンは0.8.0。
しょうがないから0.7.2バージョンをインストールし直したら、何とかインポートできた。

(途中ココも参考にして書いてある通りに試してみたけど、うまくいかなかった)

自分のPCはwindowsマシン、Pythonのバージョンは2.6。
同じような環境でこんな症状が出たら0.7以下のバージョンをインストールするのがいいのかな、と思います。

2010年9月13日月曜日

PyAudioリベンジ

引き続きPyAudio。

前回、オーディオデータをフレーム単位で扱う必要がある、ということに気づいた。

そのことを意識してPyAudioのサンプルソースを見ていたら、何やら関係がありそうな記述が。


FORMAT = pyaudio.paInt16

p = pyaudio.PyAudio()
stream = p.open(format = FORMAT,
channels = CHANNELS,
rate = RATE,
input = True,
output = True,
frames_per_buffer = chunk)


どうやらオーディオストリームを開く時に、データフォーマットをint16で定義していたみたい。
きちんとソースは読まなくては…。

ということでこの場合、1フレームは16ビット=2バイトということがわかった。

ordにいちいち一つずつデータを渡すのは面倒なのでnumpyのfrombufferメソッドに型指定して渡すと


>>> a = frombuffer(data,dtype = "int16")
>>> a
array([ 1, -4, -4, ..., 0, 0, 0], dtype=int16)


dataは無音環境で録ったマイクからのデータなので、それらしい値になっている。
めでたくオーディオデータを数値として取り出すことができた。


これまでの経緯をもとに録音、表示プログラムを改良したものがこちら。

from pylab import *
from numpy import *
import pyaudio
import sys

chunk = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 44100
RECORD_SECONDS = 10

p = pyaudio.PyAudio()

stream = p.open(format = FORMAT,
channels = CHANNELS,
rate = RATE,
input = True,
output = True,
frames_per_buffer = chunk)

inp = []

print "* recording"
for i in range(0, 44100 / chunk * RECORD_SECONDS):
data = stream.read(chunk)
inp.extend(frombuffer(data,dtype = "int16"))

print "* done"

plot(inp)
show()


出力結果は下の画像。



マイクに息を吹きかけたりかけなかったりした波形。

うまくいっているようだ。

ちなみにいろいろ調べている途中でPyAudio使って音楽ファイルにFFTかけたり、フィルタリングするコードが載ったサイトを発見した。参考までに。

オーディオデータについて

前の記事の続き。

オーディオデータがシステム内部でどういう風に扱われているのか。

pythonでwavモジュールをいじくっていたら何となく分かってきた。
以下のような形で適当なwavファイルを読み込んでデータを表示させてみた。


>>> w = wave.open("filePath","r")
>>> w.readframes(5)
'\x00\x00\x00\x00\xdb\xff\xdb\xff\xb5\xff\xb5\xff\x8f\xff\x8f\xffj\xffj\xff'


readframes()は指定されたフレーム数、データを読み出すメソッド。
で、出力されたデータを見る限り、1フレームというのは1バイトでは無いらしい。

1フレームが何バイトなのか調べてみる。


>>> r = w.readframes(5)
>>> len(r)
20


5フレーム20バイトなので1フレームは4バイト=32ビット。

よくよく考えて見ればオーディオデータの量子化ビット数が1バイトなんてことはありえないわけで。
前の記事のようなグラフが出力されるのは当たり前だ。

ということで、オーディオプログラミングではフレーム単位でデータを扱う必要があることが分かった。

2010年9月12日日曜日

PyAudio使ってみた

PyAudioを使ってオーディオ入力を取り込むプログラムをゴリゴリいじっている。取り敢えず
マイクから入力→数値データに変換→matplotlibでグラフ化してみました
というお話。

PyAudioのサイトにサンプルとして載っている、マイク入力をスピーカーからそのまま出力するプログラムを改造した。


from pylab import *
import pyaudio
import sys

chunk = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 44100
RECORD_SECONDS = 5

p = pyaudio.PyAudio()

stream = p.open(format = FORMAT,
channels = CHANNELS,
rate = RATE,
input = True,
output = True,
frames_per_buffer = chunk)

inp = []

print "* recording"
for i in range(0, 44100 / chunk * RECORD_SECONDS):
data = stream.read(chunk)
for j in range(len(data)):
for k in range(len(data[j])):
inp.append(ord(data[j][k]))
print "* done"

plot(inp)
show()



マイクから取り込んだ入力はそのまま出力すると下のようにバイトコードで出力されてしまうので、ord関数を使って数値データに変換している。

>>> data[0]
'\x00'


このプログラムを実行した結果、以下のような感じに。



…何が何だか分からない。

録音したのは無音環境だったので、ゼロ付近に張り付くグラフを予想していたんだけれど…。
単純に音の強弱が数値に変換されている訳じゃないのかな?

次はマイクから入力されたデータがシステム内部でどう取り扱われているかについて調べてみよう。

2010年7月26日月曜日

AndroidでBluetooth

AndroidでBluetoothを扱うAPIのテスト。
ということで、色々と周辺調査したので箇条書きにしてみる。


・Android用BluetoothAPIには公式のものと非公式のものがある
・公式のAPIはAndroidOSのバージョンが2.0以上で無いと使用不可
・OSのバージョンが1.0系の場合、非公式BluetoothAPIを使用する必要がある
・非公式APIにはいくつかあるが今回は"backport-android-bluetooth"を使用してみた


以下ざっくりしたbackport-android-bluetooth使用手順


1.このサイトよりbackport-android-bluetooth.jarをダウンロード
2.BluetoothAPIを使用するプロジェクトのライブラリにダウンロードしたjarファイルを追加(ココを参考に
3.マニフェストファイルにpermissionを変更する文言を追加(jarファイルをダウンロードしたサイトに載ってるヤツ
4.ソースコード内でimportする

これで使えるようになるはず。

2010年7月22日木曜日

マルチスレッドプログラミング

Androidでオーディオプログラミングの続きをしていた。

ネットでマルチスレッドを使って録音プログラム作っている人を発見[1]。
で、いじくってみようと思ったら、マルチスレッドプログラミングに関して余りにも無知なのでコードがよく理解できない…。

ということで、少し周辺知識について調べてみた。

・排他制御
複数のプログラムが一つのリソースにアクセスする際に、競合が発生しないように整合性を保つための仕組み[2]。


・同期
複数のエージェントの動作を時系列で制御すること[3]。
(エージェント:何らかの処理を行う仕組みのこと。プログラムとか)


・ハンドラ
割り込み時に実行されるプログラムのこと。
リスナーと同義[4][5]。


・セマフォ
同期機構の一種。
複数のスレッドが共有リソースにアクセスするような仕組みを作る際に、一度にアクセス出来るスレッドの数を制限したい時に使用する。
具体的にはセマフォ変数という共有変数を用いて実現される。
セマフォ変数の初期値は共有リソースに対して、一度にアクセス可能なスレッドの数である。
共有リソースにアクセスするスレッドはセマフォ変数をデクリメントする。
この時、セマフォ変数がゼロの場合、そのスレッドは共有リソースにアクセスすることは出来ない。
共有リソースへのアクセスが終了したスレッドはセマフォ変数をインクリメントする[6][7]。


・ミューテックス
同期機構の一種。
仕組みはセマフォと同じ。
セマフォ変数の初期値を1に設定したセマフォ。
複数のスレッドが共通のリソースにアクセスする際に、一つのスレッドのみにアクセス権を与えるようにして、スレッドを同期化する仕組み。
Mutexという語はMUTual EXclusion(相互排他)の略[8][9]。



・クリティカルセクション
マルチスレッドプログラミングにおいて、共有リソースを複数のスレッドが取り合うような部分のこと。クリティカルセクションを実行することが出来るスレッドの数は一つに限られる[10][11]。


参考URL
[1]http://d.hatena.ne.jp/yamanetoshi/20100202/1265116750
[2]http://ja.wikipedia.org/wiki/%E6%8E%92%E4%BB%96%E5%88%B6%E5%BE%A1
[3]http://ja.wikipedia.org/wiki/%E5%90%8C%E6%9C%9F_(%E6%83%85%E5%A0%B1%E5%B7%A5%E5%AD%A6)
[4]http://www.kab-studio.biz/Programing/JavaA2Z/Word/00000546.html
[5]http://e-words.jp/w/E589B2E3828AE8BEBCE381BFE3838FE383B3E38389E383A9.html
[6]http://ja.wikipedia.org/wiki/%E3%82%BB%E3%83%9E%E3%83%95%E3%82%A9
[7]
[8]http://ja.wikipedia.org/wiki/%E3%83%9F%E3%83%A5%E3%83%BC%E3%83%86%E3%83%83%E3%82%AF%E3%82%B9
[9]http://www-06.ibm.com/jp/domino04/pc/support/beginner.nsf/btechinfo/SYB0-014660D
[10]http://ja.wikipedia.org/wiki/%E3%82%AF%E3%83%AA%E3%83%86%E3%82%A3%E3%82%AB%E3%83%AB%E3%82%BB%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3
[11]http://www.tokumaru.org/techterm/critical_section.html

昨日の続き

昨日のAudioRecord初期化エラーやっぱりpermissionが原因だった。
下記の記述をAndroidManifest.xmlのタグの前に追加したら問題なく動作した。

<uses-permission android:name="android.permission.RECORD_AUDIO">
</uses-permission>


参考URL
[1]http://groups.google.com/group/android-group-japan/browse_thread/thread/489149ff5e91eb73
[2]http://feedyomi.blog32.fc2.com/blog-entry-181.html


※あとブログ記事の中にタグを記述する方法について下記のサイトを参考にした。
http://www.wareteki.com/movabletype/archives/2005/07/html_3.html

2010年7月21日水曜日

Android AudioRecordクラス

Androidのマイク入力を扱うためにAudioRecordクラスのテスト。
色んなサイト見てコーディングしてみた。

…がうまくいかない。

ソースはこんなん(注:実行しても動きません→追記:permissionの設定すれば動きます。この記事参照)

package org.example.microphone;

import android.app.Activity;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.media.AudioRecord.OnRecordPositionUpdateListener;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

public class Microphone extends Activity {

private static final int AUDIO_SAMPLE_FREQ = 8000;
//Bufferサイズ(getMinBufferSize()で取得できる値の2倍)
private static final int AUDIO_BUFFER_SIZE = AudioRecord.getMinBufferSize(AUDIO_SAMPLE_FREQ,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.CHANNEL_CONFIGURATION_MONO) * 2;

private static final String TAG = "debug";

AudioRecord record;
mNotification notificaiotn;
TextView textView;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

Log.d(TAG,String.valueOf(AUDIO_BUFFER_SIZE));

textView = (TextView)findViewById(R.id.textView);
setContentView(R.layout.main);

//recorderインスタンスのコンストラクタ設定
try{
record = new AudioRecord(MediaRecorder.AudioSource.MIC,
AUDIO_SAMPLE_FREQ,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT,
AUDIO_BUFFER_SIZE);
}
catch(IllegalArgumentException e){
e.printStackTrace();
}

Log.d(TAG,String.valueOf(record.getState()));

record.setNotificationMarkerPosition(50);
record.setPositionNotificationPeriod(100);
record.setRecordPositionUpdateListener(notificaiotn);


}

//オーディオ入力イベントリスナの実装
public class mNotification implements OnRecordPositionUpdateListener{

@Override
public void onMarkerReached(AudioRecord recorder) {
// TODO Auto-generated method stub

//read PCM buffer here
byte[] audioBuffer = new byte[AUDIO_SAMPLE_FREQ];
record.read(audioBuffer,0,AUDIO_SAMPLE_FREQ);

textView.setText(String.valueOf(audioBuffer));

}

@Override
public void onPeriodicNotification(AudioRecord recorder) {
// TODO Auto-generated method stub

//read PCM buffer here
byte[] audioBuffer = new byte[AUDIO_SAMPLE_FREQ];
record.read(audioBuffer,0,AUDIO_SAMPLE_FREQ);
}}

@Override
public void onPause(){
super.onPause();

}

}


どうもsetNotificationMarketPosition部分でAudioRecordのインスタンス初期化が出来ていないみたい。エラーログはこんな感じ。

07-21 21:54:24.749: ERROR/AudioFlinger(35): Request requires android.permission.RECORD_AUDIO

permissionの設定が問題なのかしら?
明日はそこら辺のいじくり方について調べるか。

----------
※参考URL
[1]http://www.mail-archive.com/android-developers@googlegroups.com/msg35441.html
[2]http://www.mailinglistarchive.com/html/android-group-japan@googlegroups.com/2009-10/msg00035.html
[3]http://d.hatena.ne.jp/yamanetoshi/20100202/1265036548
[4]http://www.mailinglistarchive.com/html/android-group-japan@googlegroups.com/2010-06/msg00617.html
[5]http://groups.google.co.jp/group/android-developers/browse_thread/thread/38cabdc4a48358a9?fwc=1
[6]http://developer.android.com/reference/android/media/AudioRecord.html

寝坊根絶

今日は寝坊してバイトをサボってしまった…。

本来起きなければいけない時間をブッちぎること4h。

昨日まで3日連続で研究室の大掃除をしていて疲れていた、なんてのは言い訳にならないわけで(じゃあ言うなよ)。
ダメじゃん、俺(関係者のみなさん、ご迷惑をお掛けしました)。


こんなダメな自分には優秀な秘書が必要だ。
キチンと時間通りに起こしてくれる秘書が(どちらかと言うと母親の役割だな、コレは)。
でも秘書を雇うカネは無い。
自分でスケジュール管理するしかない。
何とかせねば。


そんなことをボンヤリ考えているうちに、スケジュール帳から目覚ましを設定できればいいのにと思った。



自分はスケジュール管理を全部iPhone君におまかせしている。
デフォルトのカレンダーアプリとGoogleカレンダーをSynkして使っている。
このGoogleカレンダーの設定に「アラーム」みたいな設定項目を設けて、アプリ連携で設定した時間にアラーム鳴らす、みたいな感じで出来たらなと。


しかしiPhoneアプリを作るためには色々揃えなければいけないものがある。
MacPC、iPhoneアプリのDev登録…。
まぁつまりは金が必要だということだ。
普通に揃えたら10万円近くかかるであろう金が。
しかし、極貧学生の自分にそんな額の持ち合わせがある筈もない。


ということでタダで開発できるAndroidで(しかも今実機も手元にある)出来ないものかと思って、これを実現するために考え得る最大の障害、アプリ連携についてちょっと調べてみた。
ザッと箇条書きにしてみる。

・Androidでアプリ連携は可能
・アプリ間連携に用いられる「インテント」というモノがあるらしい
・インテントはアプリ間でやりとりするメッセージ
・あるアプリがインテントを発行すると、その内容を処理可能なアプリが勝手に起動して処理してくれる
・例えばTwitterクライアントでURLをクリックするとURLを含んだインテントが発行されて、Webブラウザが処理してくれる、メモ帳アプリからメール送信のインテントを発行するとメーラーが起動とか


こんな感じらしい。
インテントの存在はアプリ開発を非常にラクにしてくれそうだ。
iPhoneだと全部自分で実装しなきゃ、だから。

それに色々使い道考えるとワクワクする。

iPhoneアプリ使いながらさっきの案以外にもちょっと考えてみよう。


で、ヒマがあったらカレンダー&アラーム連携試してみよう。

参考URL http://www.atmarkit.co.jp/news/analysis/200906/29/android.html

2010年6月10日木曜日

今日は

新橋駅前にある韓国料理屋「ボクデン」でディナー。

美味かった!

落ち着いた雰囲気の店内&全体的に甘めに味付けられた料理。女性にウケが良さそう。

所狭しとセラーに並べられたワインの数々を見る限りそちらの品揃えも充実している印象。

こう言うと花より団子タイプの大食漢からは「ちょっと…」という声が聞こえてきそうな。でも、ご安心を。食べごたえがある料理もしっかり用意されていて。スペアリブやらトッボギあたりは味にメリハリがあり、ボリュームもなかなか。満腹感が味わえます。

ちょっと価格はお高目のようですが、それだけの価値はあるお店かと。同僚と来るもよし、女の子を連れて来るもよしで安定感の高さはバツグン。

唯一の欠点は内装が鏡張りのトイレ一点のみ。何だか落ち着かない…。まぁそこは(トイレ行くのを)ガマンすれば良し!と思えるくらいの良いお店でした。

2010年6月6日日曜日

NHKでやってた本田圭佑のインタビュー番組を見た。

本田△!!

ゴールを狙う意識の高さ、無回転FKに代表される高いキック技術、ビッグマウス&それを支えるパーソナリティ、といった心身ともに「個」の強さみたいなものを強く感じる選手だなと。
そんな印象を持ってました、この選手には。

今までに見たスポーツニュースなんかでも、ビッグマウス部分が強調されていて個人主義者のような扱いをされていたように思う。

そんな先入観を持ってワケなんだけど、冒頭の番組を見てみたらチームのことをよく考えている点が強く印象に残った。チームメイトに声がけしたり、移籍先の国の言語を話す努力をしていたり。んでその姿勢、実力が認められてオランダではキャプテンもやっててカイザーなんて呼ばれているというから凄いものだ。

このチームへの意識、リーダーシップも手段の一つでしかないのだろうか。
世界一のサッカー選手になるという夢。
それを実現するためにはビッグクラブで成績を残す必要がある。
ビッグクラブに入団するためには所属チームで活躍してスカウトの目に止まる必要がある。
そのためには個人としての成績もチームプレーを尊重する姿勢もアピール擦る必要がある。
というか「勝利に貢献できる選手」であるとアピールする必要がある。

だから個人でできることは何でもやる、という姿勢なのかな。

自分を売ることには貪欲に。
自分には著しく欠けている性質なので見習わないと。
ということで今からビッグマウスに生まれ変わります。

あ、あと本田さんの髪の毛見てこの前美容院で髪切ってもらったお兄さんに金髪を勧められたことを思い出したなぁ。

金髪に染める!?それはちょっと…。

せめて両腕時計くらいでとどめておきます。

2010年3月16日火曜日

「ゲームデザイン脳」

「ゲームデザイン脳」という本を読んだ。

著者の桝田省治さんは「俺の屍を越えてゆけ」や「リンダキューブ」などのゲームを作ったひと。
世間では桝田さんの作るゲームは「桝田ゲー」とか呼ばれているそうで。
自分の名前が代名詞になる、個性的なゲームを作るひと、というイメージが強い人らしい。


本の内容は、桝田さんがゲームを作る際、アイディアを搾り出し、ゲームシステムに落とし込むまでの過程を丁寧に、そして赤裸々に語っていく、というもの。

文章のリズム、テンポがイイ。
スラスラ読める。

その読みやすさを生み出している要因の一つが、この本誕生のきっかけを作った美人編集者秋山女史の存在。

美人、聡明な印象を与える外見、バリバリ仕事をこなしていてもおかしくない年齢…なんだけど、その言動を振り返ってみるとどこかチグハグな印象を与える秋山女子。
この秋山さんと桝田さんのやりとり(掛け合い?)がところどころに織りまぜられていて、インターバルとして良く機能している。


僕自身の桝田ゲーに関する記憶は少ない。
中学時代の友達に一人桝田さんゲーが好きな人がいて、その友達がいくつかの作品をプレイしているのを横目で見ていたのと、「俺の屍を越えてゆけ」をゲームアーカイブスで買ってPSPでプレイしたのと、それくらい。

どのゲームも気にはなっていたんだけど、何となく敬遠していたふしがあった。

この本読んでてその理由がちょっと分かった。


「この人はリア充だ」
そう感じた。


何ていうか自分を抑えてない感じ。
欲望を全面肯定しているような。

チラホラ「美人」に人生を突き動かされたことを語ってる辺りとか、着想を得た題材に強姦、父の死を挙げてるところとかね。



…とかなんとかいってるけどスゴく面白い本ですよ、この本は。
オススメの一冊。

2010年3月6日土曜日

「インナーゲーム」

「インナーゲーム」という本を読んだ。


テニスプレイヤーだった著者(W.T.ガルウェイさん)がテニスを題材に、スポーツやそのトレーニングへの取り組み方についての理論「インナーゲーム理論」を展開していく、という内容。

読んでて目からウロコが落ちるような話満載の良書だ。

…いや、ウロコなんて生易しいもんじゃないな。
魚だ、魚が丸ごと(それも本マグロクラスの大きさを想像していただきたい)目から飛び出るくらい。
それくらいの形容をして余りあるくらいの良い本。

以下内容。

「インナーゲーム理論」はスポーツやそのトレーニングへの取り組み方についての理論。
この理論を理解するために、押さえておかなければいけない概念がある。個人的にはコレを知ってるだけでも色々なものごとに対する見方、考え方が変わると思う。

その概念とは自分自信を「セルフ1」(自分)と「セルフ2」(自信)の二つに分けて考えるというものだ。

「セルフ1」とは自分の行動を操る司令塔。自分の意識そのものだと思ってもらえればOK。
「セルフ2」とは行動する自分自身のこと。こちらは実際に動かす体や判断を行う脳を指している。

例えばテニスをプレイしているとき、ショットをミスしてしまったとする。

そんなとき「セルフ1」は「セルフ2」に対して
「ここをこうするべきだったんだよ」とか
「次からはこうするんだ!頑張れ!」といった感じでアドバイスや命令を絶えず送り続ける。

「セルフ2」が萎縮してしまうこともつゆ知らず。
「セルフ2」の目には、この「セルフ1」の振る舞いは"おせっかい"に映ってしまうのだ。

ガルウェイさんはこういった「セルフ1」の"おせっかい"を抑えこむことがメンタル向上のカギであると、本の中で言っている。
そうすれば「セルフ2」は本来持っていた力を発揮し、スムーズな動きが出来るようになるという。

…とまあこんな感じのメンタルトレーニングに関する本です。

「セルフ1」を抑えこむための方法として客観的な視点を持つことの大事さを説いていて、根性論とは全く違うアプローチだったのがとても良かった。

この本に学生の頃に出会えていたらなぁ、と思った次第(ていうか今も学生だけど)。

「メンタルを鍛えたいけど体育会系のノリはちょっと…」という人にオススメの一冊。

2010年2月27日土曜日

Python2.6からwin32APIにアクセス

Python2.6からwin32APIにアクセスするための手段についてメモ。

ちょっと調べたところ、おおまかに分けて二つの方法があるらしい。
一つは標準ライブラリ(で言い方合ってるのかな?Pythonそれ自体をインストールした時に使えるようになるモジュール)の一つであるctypesモジュールを使ってwin32api関連のdllファイルにアクセスする方法。
もう一つはpywin32というPython用win32apiモジュールをインストールして、使用する方法。

この二つ目の方法に関しては2.6対応のインストーラがなかなか見つけられなかったのでリンクを貼っておく。

http://sourceforge.net/projects/pywin32/

具体的な話(モジュールの使い方とか)についてはまたいずれ。

2010年2月19日金曜日

「創るセンス 工作の思考」

森博嗣さんが書いた「創るセンス 工作の思考」という本を読んだ。

一言で感想を言うと、「読んだ後、無性にものづくりがしたくなる本」だった。

内容は、森博嗣さん自身がもの作りとどのように関わってきたのか、技術のセンスとは?、ものづくりのセンスを養うにはどうすれば良いか、など。

森博嗣さん自らの、作り手、教育者としての経験、視点に基づいた分かりやすい、説得力のある内容だと思う(森さんは工学博士。大学で建築学の研究や学生への指導をしている)。

また、もの作りというテーマを通して、楽しさや好奇心を持つには?といった、「生きるセンス」にもついても言及されていて、ものづくりの経験が少ない人にもオススメ出来る一冊。

さてと、明日から何を作りはじめようかな…。

2010年2月18日木曜日

blogはじめました。

ちょっとしたメモやふと思いついたこと、考えたことを書き留めていきたいと思います。