2006年12月14日木曜日

Webカメラでテルミン



OpenCVで画像とりこんで、SDLで音を鳴らす。


そんなデモを作ってみました。明るい点を見つけてそれでテルミンになります


http://saife.dip.jp/~akira/vtel.avi


(ちなみに、手にもっているのは発光ダイオードです)


なんと100行でこんなプログラムがかけちゃうのです。


OpenCVもSDLも良い子です。





#コレを作りたくて、かわしんさんの電話ぶっちしちゃいました。


#ごめんなさい。






#pragma comment(lib, "cv.lib")
#pragma comment(lib, "cvaux.lib")
#pragma comment(lib, "cvcam.lib")
#pragma comment(lib, "cvhaartraining.lib")
#pragma comment(lib, "highgui.lib")
#include <stdio.h>
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
#include <math.h>

#pragma comment(lib, "SDL.lib")
#include <SDL.h>
#include <SDL_audio.h>
const double pi=3.1415926535897932384;

/***************audio**************/
void playASound(char *file);
void mixaudio(void *unused, Uint8 *stream, int len);

void initAudio(void){
//音の初期化
extern void mixaudio(void *unused, Uint8 *stream, int len);
SDL_AudioSpec fmt;

/* 44100khz の 16-bit ステレオ に設定 */
fmt.freq = 44100;
fmt.format = AUDIO_S16;
fmt.channels = 1;
fmt.samples = 4069; /* ゲームには良さげな値 */
fmt.callback = mixaudio;
fmt.userdata = NULL;
/* オーディオデバイスをオープンしてサウンドの再生を開始! */
if ( SDL_OpenAudio(&fmt, NULL) < 0 ) {
fprintf(stderr, "Unable to open audio: %s\n", SDL_GetError());
exit(1);
}
SDL_PauseAudio(0);

}

/*音再生ルーチン*/
#define HZ_RATE (2.0*pi/44100.0)
static double deltaTheta= 440.0*HZ_RATE;
static double gain=1;
void mixaudio(void *unused, Uint8 *stream, int len)
{
static double theta=0;
double a;
int i;
a=65534.0/2.0*gain;
for(i=0;i<len/2;i++){
((short *)stream)[i]=(short)(a*sin(theta));
theta+=deltaTheta;
if(theta>2*pi)theta -= 2*pi;
}
}
void setFreq(double freq){
SDL_LockAudio();
deltaTheta= freq*HZ_RATE;
SDL_UnlockAudio();
}
void setGain(double inGain){
SDL_LockAudio();
gain=inGain;
SDL_UnlockAudio();
}
/****************以上audio************/


int loop(void){
int key;
CvCapture* capture = NULL;
IplImage* img = NULL;
char* captureWindow = "Capture";

initAudio();
if(NULL==(capture = cvCaptureFromCAM(-1)))
{
printf("カメラが見つかりません");

return -1;
}

cvNamedWindow(captureWindow, CV_WINDOW_AUTOSIZE);
img = cvQueryFrame(capture); //キャプチャサイズを知るために画像取得
IplImage * gImg = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);
while(1)
{
img = cvQueryFrame(capture);
cvCvtColor(img, gImg, CV_BGR2GRAY);
CvPoint minPos,maxPos;
double min,max;
cvMinMaxLoc(gImg,&min,&max,&minPos,&maxPos);
if( ( (200<min*2)?200:(min*2) ) <max)printf("%03d,%03d\n",maxPos.x,maxPos.y);

double freqRate;
freqRate=(double)maxPos.y/img->height;
setFreq(pow(2,2*freqRate-1)*440);

double gainRate;
gainRate=(double)maxPos.x/img->width;
setGain(1.0-gainRate);

cvShowImage(captureWindow, gImg);

key = cvWaitKey(1);
if (key == 0x1b)
{
break;
}
}

cvReleaseCapture(&capture);
cvDestroyWindow(captureWindow);
return 0;
}





0 件のコメント:

コメントを投稿