MuMu rooMu Blog

むむっとなる情報を!
MENU
日常

いまやっていること

やたら「自主研究で何してるの?」と聞かれるので、このページいけよb と言えば終わるように
もう書いておこうと思ったわけです。

正直自分でも何やってるか分からないし、Cの方はほとんど教授に書いていただいたものとネットに
落ちてるものの出来合いみたいな感じなんで、説明なんて恐れ多いんですが
いちおう「こういう風にしたいんだよね」っていう説明は入れますbb

おおまかには、
まず、MATLABで畳みこみの波形を作り、それwavで出力。
そしてそれをCで、インターフェースから取り込んだ音にかけ合わせて出力
といった感じですかね。

まずMATLABでの畳みこみのプログラム。

――――――――――――――――――――――――――――――――――――――

s_conv48.m
%サンプリングレート48000Hz
%畳みこみによって、5回の分の処理を行う
%2.5秒で0.5秒ずつインパルス応答出力
%グラフで波形を出力し、conv.wavを出力する

clear all;
close all;

data = 1;fs = 40000;bit = 2;
%[data,fs,bit]=wavread('found.wav');

z=[1;2;3;4;5];

imp_res=zeros(fs,1);
imp_res(1,1)=1;
imp_res(z*(fs/(24/10)),1)=(1/2).^z;

out_data=conv(data,imp_res);

subplot;plot(out_data);
title('effected data');
xlabel('time');
ylabel('frequency');
axis([0 10*10^(4) -1 1]);
grid;

wavwrite(out_data,fs,'conv.wav');

――――――――――――――――――――――――――――――――――――――

これで、音声信号を処理するためのもととなる波形が出来上がるわけです。

つまりフィルターですね。

画像あればもっとわかりやすいですが、まぁ適当に理解してください!(ぇ

そのあと、C言語でフィルターを通す作業になるわけです。
ALSAを使います。したがってコンパイル時はリンカで-lasoundを渡すことのなります。
また、俺も把握しきれていないincludeや言葉もいっぱいあるんですが、
大まかにはインターフェースに入れられた信号を読み取り、それをバッファに格納
バッファからフィルター掛けて、音を出力ってことです。

また、オレが完成させたプログラムとは言い難いので、コピペしても動かないようにしてます←
知識ある人は間違い探しで治せるかも。

まぁ、どの道、いまはアンダーランするから、関係ないかもですが←


――――――――――――――――――――――――――――――――――――――

#include
#include
#include
#include

#define SFm 48
#define Ch 2
#define By 2
#define S_BUF 50
#define S_RING 400

int main ( void ){
 int p_err, r_err;
 unsigned int i,j;

 snd_pcm_t* p_handle;
 snd_pcm_t* r_handle;
 snd_pcm_sframes_t p_frames,r_frames;

 unsigned char *p_buffer,*r_buffer;
 unsigned char *ring_buffer;
 int p_i,ring_i;
 int size_buffer, size_ring_buffer;

 short *s_ring_buffer;
 double temp;


 static char *p_device = "hw:0,0";
 static char *r_device = "hw:1,0";

 fprintf(stdout,"one\n");
 //メモリの確保
 r_buffer=(char *)malloc(SFm*By*Ch*S_BUF);
 ring_buffer=(char *)malloc(SFm*By*Ch*S_BUF*S_RING);
 s_ring_buffer=(short *)malloc(SFm*Ch*S_BUF*S_RING);

 fprintf(stdout,"two\n");
 // PCMストリームを開く
  if ((p_err=snd_pcm_open(&p_handle,p_device,SND_PCM_STREAM_PLAYBACK,0))<0){
   printf("Playback open error: %s\n",snd_strerror(p_err));
   return 1;
   }
  if ((r_err=snd_pcm_open(&r_handle,r_device,SND_PCM_STREAM_CAPTURE,0))<0){
   printf("Playback open error: %s\n",snd_strerror(r_err ));
   return 1;
  } 

 // 符号付き16bit
  const static snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE;
  // snd_pcm_readi/snd_pcm_writeiを使って読み書きする
  const static snd_pcm_access_t access = SND_PCM_ACCESS_RW_INTERLEAVED;
  // チャネル数
  const static unsigned int channels = 2;
   // 再生周波数 48kHz
   const static unsigned int sampling_rate = 48000;
   // ALSAがサウンドカードの都合に合わせて勝手に再生周波数を変更することを許す
   const static unsigned int soft_resample = 0;
  // 20ミリ秒分ALSAのバッファに蓄える
  const static unsigned int latency = S_BUF*1000;
  fprintf(stdout,"three\n"); // 確認用
   // 再生周波数、フォーマット、バッファのサイズ等を指定する
   if((p_err=snd_pcm_set_params(p_handle,format,access,channels,sampling_rate,soft_resample,latency))<0){
   printf("Playback open error: %s\n",snd_strerror(p_err));
   return 1;
  }
   if((r_err=snd_pcm_set_params(r_handle,format,access,channels,sampling_rate,soft_resample,latency))<0){
    printf("Playback open error: %s\n",snd_strerror(r_err));
   return 1;
  }

    ring_i = 0;
    size_buffer=SFm*By*Ch*S_BUF;
     size_ring_buffer=size_buffer*S_RING;

     fprintf(stdout,"while\n");
   int c=0;
   int n=10;
    while(1){
     if (c%10==0){
      fprintf(stdout,"c=%d\n",c);
    }
   c++;
   r_frames=snd_pcm_readi(r_handle,r_buffer,(long)(size_buffer/(2*channels)) );
    while(1){
     if(r_frames<0){
      printf("snd_pcm_readi failed: %s\n",snd_strerror(r_frames));
        r_frames=snd_pcm_recover(r_handle,r_frames,0);
        r_frames=snd_pcm_readi(r_handle,r_buffer,(long)(size_buffer/(2*channels)) );
    //   break;
     }else{
      break;
     }
    }
    if(r_frames>0 && r_frames<(long)size_buffer/(2*channels)){
     printf("Short read (expected %li, read %li)\n",(long)size_buffer,r_frames);
     break;
    }
    memcpy(ring_buffer+ring_i, r_buffer, size_buffer); // 読み込んだデータをリングバッファに格納
    memcpy(s_ring_buffer+ring_i/2, r_buffer, size_buffer); // short型のメモリ領域にデータをコピー

   for (i=0;i      temp=0.0;
   for (j=0;j     temp = temp + (double)(*(s_ring_buffer+ring_i/2+i+j));
    // fprintf(stdout,"i:%d\td:%f\ts:%d\n",i,temp,*(s_ring_buffer+ring_i/2+i+j));
     }
    *(s_ring_buffer+ring_i/2+i)=(short)(temp/n);
      // fprintf(stdout,"i:%d\ts:%d\n",i,*(s_ring_buffer+ring_i/2+i));
     //*(s_ring_buffer+ring_i/2+i)=*(s_ring_buffer+ring_i/2+i);
    }
    memcpy(ring_buffer+ring_i,s_ring_buffer+ring_i/2,size_buffer); // 読み込んだデータをリングバッファに格納
    ring_i=(ring_i + size_buffer) % size_ring_buffer; // リングバッファのアドレスを読み込んだバイト数分進める。

    fp = fopen("conv.wav", "r");
    int con=fgetc(fp);

    p_i=(ring_i-size_buffer)*con; //リングバッファにフィルターを通す
    fclose(fp);

    if (p_i<0){ // リングバッファ内にアドレスを含めるための例外処理
     p_i=p_i+size_ring_buffer;
   }
    if (p_i>=size_ring_buffer){ // 同上
    p_i=p_i-size_ring_buffer;
   }
   p_buffer=ring_buffer+p_i; //再生バッファアドレスの指定
     //fprintf(stdout,"ring_i=%d \t p_i=%d \n size_ring_buffer=%d \t p_buffer=%p\n",ring_i,p_i,    size_ring_buffer,p_buffer); // 確認
   while(1){
   if(p_frames<0){
    p_frames=snd_pcm_recover(p_handle,p_frames,0);
    p_frames=snd_pcm_writei(p_handle,p_buffer,(long)(size_buffer/(2*channels)) ); // デバイスに書き込み
   }else{
    break;

    }   
    if(p_frames<0){
     printf("snd_pcm_writei failed: %s\n",snd_strerror(p_frames));
       }
     if(p_frames>0 && p_frames<(long)size_buffer/(2*channels)){
       printf("Short write (expected %li, wrote %li)\n",(long)size_buffer,p_frames);
         }


   snd_pcm_close(p_handle);
  snd_pcm_close(r_handle);
  return 0;
}


――――――――――――――――――――――――――――――――――――――

まぁ大体こんな感じ。

けどね、まだまだ問題解決には遠そうなの・・・

いっそ音つぶしたりするような路線にしよぷか・・


とりあえず、腹減ったので飯作るぜ!

腹減って飯作る気も起きないがな・・・(ぇ

スポンサーサイト

Leave a reply






管理者にだけ表示を許可する

Trackbacks

trackbackURL:http://blogofmumumu.blog55.fc2.com/tb.php/757-81fde505
該当の記事は見つかりませんでした。