2009-09-19 70 views
0

嘿,那裏,只是練習,我有一個問題。我有一個程序(源代碼如下),在文本中打印出一個wave。當波到達終端的外部時,我用一個叫做noise()的函數發出一個噪音。但是當這個函數被調用時,它暫停動畫直到它完成噪聲,然後動畫再次開始。運行函數暫停父函數

我想知道是否有人知道兩種功能同時發生的方式。我應該fork()它還是有更好的方法?

我提到的代碼是晶格函數和噪聲函數。

波紋管是完整的源代碼,以我的程序:

#include <stdio.h> 
#include <stdlib.h> 
#include <sys/ioctl.h> 
#include <ao/ao.h> 
#include <math.h> 

#define BUF_SIZE 4096 

int main (int argc, char *argv[]) {  //check for whitch effect to print 
    int i = argc; 
    for(i > 0; i--;) { 
     switch(*argv[i]) { 
      case '1': 
       lattus(); 
       break; 
      case '2': 
       normal(); 
       break; 
      case '3': 
       noise(50); 
       break; 
      default: 
       break; 
     } 
    } 
} 


char *randstring (char *buffer, int length) {  //genertate a random number 
    int i = length; 
    for(i >= 0; i--;) { 
     buffer[i] = (rand() % 2) ? '1' : '0'; 
    } 
    buffer[length] = 0; 
    return buffer; 
} 

int normal(){   // normal drawing of 1's and 0's 
    struct winsize w; 
    ioctl(0, TIOCGWINSZ, &w); 
    int width = w.ws_col; 
    int height = w.ws_row;  //get terminal width and height 
    char buffer[width*height + 1]; //create a buffer big enough to hold one draw to the screen 
    int i = 25; 
    while(i-- >= 0) { 
     printf("%s\n", randstring(buffer, width*height)); //draw to screen 
     usleep(50000); 
    } 
    system("clear");  //clear screen 
} 

int noise(int pitch) { 
    int second = 1; 
    int freq = (second * pitch); 
    ao_device *device; 
    ao_sample_format format; 
    int default_driver; 
    char *buffer; 
    int buf_size; 
    int sample; 
    ao_initialize(); 
    default_driver = ao_default_driver_id();  
    format.bits = 16; 
    format.channels = 2; 
    format.rate = 44100; 
    format.byte_format = AO_FMT_LITTLE; 
    buf_size = format.bits/8 * format.channels * format.rate; 
    int b = 10; 
    device = ao_open_live(default_driver, &format, NULL /* no options */); 
    buffer = calloc(buf_size, sizeof(char)); 
    for (b = 0; b < format.rate; b++) { 
     sample = (int)(1 * 532768.0 * sin(2 * M_PI * freq * ((float) b/format.rate))); 
     /* Put the same stuff in left and right channel */ 
     buffer[2 * b] = buffer[2*b+2] = sample & 0xff; 
     buffer[2*b+1] = buffer[2*b+3] = (sample >> 8) & 0xff; 
    } 
    ao_play(device, buffer, buf_size); 
    buffer = 0; 
    ao_shutdown(); 
} 

int lattus (void) { 
    struct winsize w; 
    ioctl(0, TIOCGWINSZ, &w); 
    int width = w.ws_col;  //get the terminal width 
    char *buffer1 = malloc(sizeof(char) * (width + 1)); //create 3 buffers for each segment 
    char *buffer2 = malloc(sizeof(char) * (width + 1)); //each big enough to hold the width of the terminal 
    char *buffer3 = malloc(sizeof(char) * (width + 1)); 
    int first = 1;   //how many before the space 
    int second = width - 8;  //how many in the middle of the space 
    int third = 1;   //how many at the end of the space 
    int i = 1000;   //draw 1000 lines 
    int on = 0;   //switch for growing and shrinking 
    while(i-- >= 0) { 
     usleep(9000); 
     if(first == 1 && third == 1 && second == width - 8 || second == width - 9) { //is it at min? 
      if(second % 2 == 0) {  //is it an even number (had problems with buffer if it was odd) 
       second = second - 2; 
      } else { 
       second = second - 3; 
      } 
      first ++; 
      third ++; 
      on = 0;  //keep growing 
      noise(10); //make lower noise 
     } else if(first == (width - 8)/2 && third == (width - 8)/2 && second == 2) { //untill it gets to max 
      if(second % 2 == 0) { 
       second = second + 2; 
      } else { 
       second = second + 1; 
      } 
      third --; 
      first --; 
      on = 1;  //start shrinking 
      noise(30); //make higher noise 
     } else if(on == 0) { //else if suppost to grow, grow 
      second = second - 2; 
      third ++; 
      first ++; 
     } else if(on == 1) { //else if suppost to shrink shrink 
      second = second + 2; 
      third --; 
      first --; 
     } else { 
      break; 
     } 
     printf("%s %s %s\n", randstring(buffer1, first), randstring(buffer2, second), randstring(buffer3, third)); //print it out 
     //wait(); 
    } 
    system("clear"); //clear screen 
} 

回答

1

顯然ao_play是阻塞的,所以你需要一個線程或分叉進程。我不知道分叉的延遲(對於您的目的而言可能相當低),但線程顯然更適合。

如果新的「播放聲音」事件可能與主動聲音的持續時間重疊,您最終會考慮混音。特別是如果重疊的聲音是可能的,我會有一個專用的fork或線程,它是唯一調用ao_play的函數,並向它發送消息,而不是每次都啓動一個新的fork或thread。

+0

聽起來是對的。生病去看看。謝謝。 – austin 2009-09-19 01:41:30

+0

我有一個問題,我有pthreads的工作,但我不知道如何去發送函數之間的消息...我怎麼做到這一點? – austin 2009-09-19 02:08:16

+0

pthread條件變量將成爲您的消息。音頻線程將等待它發出信號(接收消息)。繪圖線程是更新它(發送消息)的線程。 – mocj 2009-09-19 02:25:48

1

我會建議使用線程和pthreads使用條件變量同步音頻到邊緣碰撞。

+0

感謝您的鏈接 – austin 2009-09-19 01:42:06