запущенная функция приостанавливает родительскую функцию - PullRequest
0 голосов
/ 19 сентября 2009

Привет, просто тренируюсь, и у меня возник вопрос. У меня есть программа (источник ниже), которая печатает волну в тексте. когда волна попадает за пределы терминала, у меня возникает шум с помощью функции noise (). но когда эта функция вызывается, она приостанавливает анимацию до тех пор, пока не завершит создание шума, затем анимация начинается снова.

Мне было интересно, знает ли кто-нибудь, как эти две функции происходят одновременно. я должен разветвляться () это или есть лучший способ?

код, к которому я обращаюсь, это функция lattus и функция шума.

ниже - полный источник моей программы:

#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
}

Ответы [ 2 ]

1 голос
/ 19 сентября 2009

Ясно, что ao_play блокирует, так что вам нужен поток или разветвленный процесс. Я не знаю задержку разветвления (она, вероятно, довольно мала для ваших целей), но потоки явно лучше подходят.

Возможно, вы захотите микшировать, если новые события «воспроизведения звука» могут перекрываться с продолжительностью активного звука. Особенно, если возможны перекрывающиеся звуки, я бы выделил отдельный ветвь или поток, который будет вызывать ao_play и отправлять ему сообщения, вместо того, чтобы каждый раз запускать новый ветвь или поток.

1 голос
/ 19 сентября 2009

Я бы предложил использовать многопоточность, используя pthreads и используя условную переменную для синхронизации звука с краевым столкновением.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...