cmdcatch
cmdcatchがおもしろい。すごくおもしろい。
おもしろいのだが、mplayerはないだろ、maplyerは。とか言いそうになった。
あと、なんかうちの環境だとコイーン、コイーン、コイーン...と連コインになってくれない。
個人的にはココココココココ...ココココイーンって感じでスクラッチしてほしい。
とか言うくらいなら自分で書けばいいのか。
なんとなく思いつきでファイル名はrencon.cc
どうでもいいがレンコンはうちの地元土浦の名産品だ。
久々のccで結構戸惑った。
#include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <signal.h> #include <fcntl.h> #include <stdlib.h> #define BUFFER_SIZE (8000*10) #define nCOINS_ONEUP 100 #define SLEEP_TIME (1000*100) int g_coin_pos = BUFFER_SIZE; int g_oneUp_pos = BUFFER_SIZE; int g_dead_pos = BUFFER_SIZE; int g_cnt = 0; // シグナルハンドラの設定。定型文 void install_signal( int signum, int flags, void (*handler)(int)) { struct sigaction act; act.sa_handler = handler; sigemptyset( &act.sa_mask ); act.sa_flags = flags; sigaction( signum, &act, NULL ); } //音を頭から再生するようにrewindする(スクラッチをかけるための。 void rewinder( int signum ) { switch( signum ) { case SIGUSR1: // get coin♪ g_cnt++; if( g_cnt >= nCOINS_ONEUP ) { g_cnt -= nCOINS_ONEUP; g_oneUp_pos = 0; } g_coin_pos = 0; break; case SIGUSR2: // you die g_dead_pos = 0; break; } } int main( int argc, char** argv ) { // コインの音 int fd_coin = open( "coin.raw", O_RDONLY ); char* coin_buf = (char*)malloc( BUFFER_SIZE ); ssize_t coin_size = read( fd_coin, coin_buf, BUFFER_SIZE ); close( fd_coin ); // 1アップの音 int fd_oneUp = open( "oneUp.raw", O_RDONLY ); char* oneUp_buf = (char*)malloc( BUFFER_SIZE ); ssize_t oneUp_size = read( fd_oneUp, oneUp_buf, BUFFER_SIZE ); close( fd_oneUp ); // 死亡 int fd_dead = open( "dead.raw", O_RDONLY ); char* dead_buf = (char*)malloc( BUFFER_SIZE ); ssize_t dead_size = read( fd_dead, dead_buf, BUFFER_SIZE ); close( fd_dead ); // /dev/dspを開く。 int fd_dsp = open( "/dev/dsp", O_WRONLY ); // シグナルハンドラをセット install_signal( SIGUSR1, 0, rewinder); install_signal( SIGUSR2, 0, rewinder); while( 1 ) { if( g_dead_pos < dead_size ) { // 死亡音 write( fd_dsp, &dead_buf[g_dead_pos], 1 ); g_dead_pos++; g_oneUp_pos++; g_coin_pos++; } else if( g_oneUp_pos < oneUp_size ) { // 1アップ write( fd_dsp, &oneUp_buf[g_oneUp_pos], 1 ); g_oneUp_pos++; g_coin_pos++; } else if( g_coin_pos < coin_size ) { // コイン write( fd_dsp, &coin_buf[g_coin_pos], 1 ); g_coin_pos++; } usleep( SLEEP_TIME ); } close( fd_dsp ); return 0; }
"coin.raw", "ounUp.raw", "dead.raw"は適宜適当に用意してください。
形式は、"/dev/dsp"を直叩きしてるので、"/dev/dsp"に合わせてください。
うちの環境だとMono, 8000Hz, sample size 1byte, unsigned
ということで
sox -t wav -v 0.5 src.wav -t raw -c 1 -1 -u -r 8000 dest.raw
ってな感じで変換できます。
-tはファイル形式、-vはヴォリューム、-cはチャンネル数、-1はサンプルサイズ、-uはunsigned、-rはrateです。
あ、バッファのサイズ決め打ちなんで、大きいファイルを使いたいときは、BUFFER_SIZEを十分大きくしてくださいな。
使い方ですが、とりあえずどっかでrenconを起動しておく。
で、killallなんかを使ってrenconへユーザシグナルを送ります。
USR1で、コインゲット。100コインで1アップします。
USR2は死亡、問答無用で死亡音が流れます。
cmdcatchのmplayerの部分を"killall -USR2 rencon"(ng) "killall -USR1 rencon"(ok)にすればおっけー。
まぁ、大したプログラムでもないので説明はなしです。
死亡音が優先されるので死亡音がながれている間はコインも1アップも鳴らない、のは仕様です。
で、これ作ってたらカタワラにいたid:viver本人がRuby版作り始めちゃいました。
そのうち向こうにruby版がcoinsdとかいう名前で上がると思うのでそちらをお使いください。
たしか向こうはrawなんてひどいファイル使わなくて済むハズですので。