|
■ /dev/dspを用いた、FreeBSD(Linux)サウンドプログラミング。 | ||||||||||||
|
研究で、どうしても、サウンド関連のプログラムをしなければならなくなったので、しょうがないので、webなどを検索してみましたが、意外に再生部分の解説はあるのですが、録音部分の解説はあまり見つかりませんでした。まぁ、出るか入るかの違いなので、そんなに、できる人には難しくないのですが、拙僧のように、猿真似しかできない人間にはつらかったので、簡単にどういう感じでやるかということに。ただ、勘違いしないでほしいのが、筆者は、音の専門家でもなく、またプロフェッショナルな理系でも無いため解説はいいかげんで、使えればいいやてきなところなでいくので.... ■/dev/dspを確認せよ
とりあえず、/dev/dspがあること(あることはあるが動いてないかもしれない)を確認してください。cat /dev/sndstatあたりで、どのカードが認識されてるかなど、しることもできますが、最近のLinuxなどだと、自動的に設定されてるかもしれません。FreeBSDは最近の、PCIカードのサウンドカードだとdevice pcmをカーネルにくわえて再コンパイルすれば認識してくれます。と、ここらへんは他のページのほうがくわしいので、ここでは詳しくはのべません。というわけでほんとに動いてるかどうか確認するには、 /dev/dspからながれてくるのは、一体どういうデーターが流れているのでしょう?ためしに、マイク入力に何らかの曲をながして、 cat /dev/dspの出力を見てみましょう。出力を眺めると、xyzzuなと、なんか、けっこーアルファベットの順に成っています。つまり、波形の線形的性質を現してるといってもいいでしょう。サンプリングレートが十分たかければ、xからaなどというのは、あまりないっていうそういう話はどーでもいいということで....つまり、あとは、/dev/dspをオープンして、ふつーにファイルとしてよみとればいいです。
とりあえず、サンプルプログラムをのせておきます。ほんとのほんとに、サンプルプログラムなんで、あまり詳しくつっこまれると泣きます。 一番簡単なサンプル
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/soundcard.h>
#define DSP_IN "/dev/dsp"
#define DSP_OUT "/dev/dsp"
main()
{
int sound_card;
unsigned char s[50];
unsigned int output_data;
int parm,status,bits,sampling;
if ((sound_card = open(DSP_IN, O_RDWR|O_NONBLOCK)) < 0) {
perror(DSP_IN);
exit(1);
}
/* set mono */
parm = 0; //0 is mono. 1 is streo.
status = ioctl(sound_card , SNDCTL_DSP_STEREO, &parm);
if (status < 0) {
perror("error from sound device ioctl");
exit(-1);
}
/*set 8bit sampling */
bits = 8;
status = ioctl(sound_card, SOUND_PCM_WRITE_BITS, &bits);
if (status < 0) {
perror("error from sound device ioctl");
exit(1);
}
/* set 8000Hz(8khz) sampling rate */
sampling = 8000;
status = ioctl(sound_card , SOUND_PCM_WRITE_RATE, &sampling);
if (status < 0) {
perror("error from sound device ioctl");
exit(1);
}
while(1)
{
int flg;
memset( s, '\0', 50);
do{
flg = read( sound_card ,&s,1);
}while((flg == 0)||(flg == -1));
output_data = (unsigned int)(s[0]);
printf("%d\n", (int)(output_data-128)); //8bit data
}
}
上記のプログラムは、かなり簡潔なプログラムです。流れとしては、 ↓ モノラル出力にセット ↓ 8bitサンプリングにセット ↓ 8khzのサンプリグレートにセット ↓ readにて、/dev/dspよりの読み込み 流れとしては、上のとおりです。。また、モノラル出力から、8khzのサンプリングレートの設定などは、ioctlをつかいデバイスに命令を与えているだけです。なので、ioctlに与える命令をかえれば、いろいろ出力をかえることができます。基本的にioctlで、デバイスに要求し、その処理をするのが、デバイスドライバの役割です。よって、サポートされてないサウンドカードにたいしては、直接たたく方式もあるのでしょうが、やったことないので、ここでは述べません。そのうち、USBをほげりたおす計画であるので、その時にしましょう。 ■各種ioctrlの意味
ioctlについて、manでしらべてみると、
/* set mono */ parm = 0; //0 is mono. 1 is streo. status = ioctl(sound_card , SNDCTL_DSP_STEREO, &parm);
上の分は、/dev/dspにたいして、出力はモノラルでお願いといっています。ちなみに、第一引数の、sound_cardは、/dev/dspでopenで帰されたファイル記述子。SNDCTRL_DSP_STEREOは、どういう要求か、parmは、変数です。書いてあるとおり、parmに0を入れると、モノラル、1だとステレオです。また、SNDCTRL_DSP_STEREOなど他にもいろいろな要求するための、キーワードなのですが、sys/soundcard.hにたっぷり書いてあります。locate soundcard.hとでもして探してください。また、これらが特に、詳しく解説されているページとして、 以下は440HZの正弦波を、ステレオで左右同位相でながしました。Gnuplotで作成したグラフです。モノラル出力の場合が左、ステレオ出力の場合が右です。
つぎに
/*set 8bit sampling */
bits = 8;
status = ioctl(sound_card, SOUND_PCM_WRITE_BITS, &bits);
if (status < 0) {
perror("error from sound device ioctl");
exit(1);
の部分なのですが、この部分は量子化ビット数なのですが、ここでは8bitにセットしています。bits = 8 の部分をbits = 16としたならば、16bitになります。もちろん16bitのほうが音の再現性はよろしいですが、データー量もでかくなります。ここで注意したいのが、8bitで出力されてくるデーターはunsigned char で、16bitsの場合はshort intです。筆者はこれにはまり、はじめモノラルにセットしてるのに、ステレオに出てるぞーとか呆けたことをいってました。もちろん、中間値がちがいます。
□そこはかとなくLinux(C3Magazine) http://www.c3.club.kyutech.ac.jp/c3mag2/LINUX/index.html 上のページはwaveも再生なども書いてあり、とても参考になりました。ありがとうございます。 /* set 8000Hz(8khz) sampling rate */ sampling = 8000; status = ioctl(sound_card , SOUND_PCM_WRITE_RATE, &sampling); PCMであると、4000-44100HZまで設定できます。CD音質で録音しおうとするととんでもないデーター量になることがわかります(最近だとそうでもないですね2001年6月現在、256MBが4000円ぐらいなわけですから)。長時間録音の場合、うまく、データーをディスクなどに書き込むなどして録音する必要があります。そのうち、音などは、無限に録音できるぐらいのメモリー容量になりそうですが.....実際、現在でもHDDを使えば、無圧縮でも、1日ぐらいは録音できるレベルにある。というわけで、samplingに具体的に数字をいれれば、サンプリングレートが変わります。
do{
flg = read( sound_card ,&s,1);
}while((flg == 0)||(flg == -1));
あとは、こいつから読み出してやるだけ、flg == -1 のときはエラーなので、ちゃんと、エラー処理をしっかりすべきですね。 ■cool Link
□そこはかとなくLinux(C3Magazine) |