Как я могу сохранить 50 мс до и после звукового события в кольцевом буфере? - PullRequest
2 голосов
/ 20 мая 2019

Я обрабатываю набор данных из 17 часов аудио .wav (16-битная PCM, 192 кГц), чтобы имитировать обработку в режиме реального времени, которая будет встроена в ESP32, Arduino DUE или в RASP, в зависимости отрезультаты.

Как мне теперь с этим справиться?

Сначала я сократил 17-часовой файл в 1-минутных выборках, после того как создал программу на C, котораяпревращает этот файл в .CSV (перепрыгивая всю главу .wav и занимая только поле даты).

PS: я выбрал CSV, чтобы данные были в лучшем расположении для выполнения тестовв Scilab для проверки алгоритмов.

С помощью этого сгенерированного файла .CSV я запускаю его во второй программе, которая открывает этот файл и заполняет круговой буфер 130 мс (24900 значений), когда буферполный код начинает вычислять среднеквадратическое значение (среднеквадратичное значение) в движущемся окне с перекрытием 10 мс, размер окна 30 мс.Когда я получаю значение больше 1000, это считается событием.

Ниже вы можете увидеть иллюстрацию проблемы:

Delimiters of an Event, Inicio = Start, Fim = End

Здесь показано окно с 50 мс до и после события, которое я имею в виду:

Window os 200ms, 50ms before and after and event of 100ms

PS: Inicio, Fim и Janela означаютсоответственно Start, End, Window.

Мой вопрос:

Как мне сохранить эти 50 мс до и после события, так как событие может произойти где угодно в буфере?И что мне делать, если событие длится более одного окна?

Некоторые данные, которые помогут понять:

130ms = 24900 values ​​from my .csv file
50ms = 9600   values
30ms = 5700   values
10ms = 1920   values

Я искал несколько источников, но большинство DSPбиблиографии и структуры данных рассматривают эти темы поверхностно, просто иллюстрируя, что такое циклический буфер, а не то, как с ним обращаться полезным.

Вот мой набросок кода, который, кажется, неверно подходит кпроблема, но я действительно не знаю, как поступить, в этом случае я создал набор данных от 1 до 100 для простоты отладки:

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<math.h>

    // Define the size of window 50ms
    #define window_size 3 // 30ms
    #define buffer_size 13 // 130ms = 50ms + 30ms + 50ms

    int main()
    {
        //define variables.
        int buffer[buffer_size]={0}; // create the buffer with 150ms;
        int write = 0;
        int i = 0, j = 0;
        int read = 0;
        int read1 =0;
        int write1 = 0;
        int counter_elements = 0;
        int number_lines = 0;
        int save_line = 0;
        char c;
        char str[1024];     // array to hold characters in a conversion of char to int.
        int inicio = 0, fim = 0;
        //RMS
        int soma_quadrado = 0;
        int rms = 0;
        int pre_amostragem[5] = {0};

        //Define variaveis referentes a leitura do arquivo e manipulacoes do mesmo.
        FILE * fp;
        FILE * LOG;
        FILE * log_rms_final;

        // Open the file and verify is NULL.
        if((fp = fopen("generator.txt","r")) == NULL)
        { // Define o nome do csv para abrir
            printf("Error! Can't open the file.\n");
            exit(1);
        }
        // store rms values
         LOG = fopen("RMSValues.csv", "a");
        // store the 50ms after and before a event.
        log_rms_final = fopen("Log_RMS.csv","a");

        int lines = 0;
        while(!feof(fp))
        {
            fgets(str,1024,fp); //reads 1024 characters and store in str.
            buffer[write] = atoi(str);
            write = (write + 1) % buffer_size; // circular
            counter_elements++; // sum 

        c = fgetc(fp);
        if(c == '\n')
        {
            lines++;
        }
        printf("%d\n", lines);
            //if buffer is full
            if(counter_elements == buffer_size)
            {
                // window
                read1 = read; 
                for(i = 0; i < window_size; i++)
                {
                    //square and sum.
                    soma_quadrado += buffer[read1]*buffer[read1];
                    read1 = (read1 + 1) % buffer_size;
                }

                // RMS 
                rms = sqrt(soma_quadrado/window_size);

                fprintf(LOG, "\n %d", rms); // store

                if(rms > 1000)
                {
                    printf("rms: %d\n",rms);

                    // store the 50ms befor a event and the window.
                    write1 = write;
                    for(j = 0 ; j < 5; j++)
                    {

                        write1 = (write1 + (buffer_size - 1)) % buffer_size;
                        pre_amostragem[j] = buffer[write1];
                    }

                    fprintf(log_rms_final,"%s","\n");

                    for(j = 4; j >= 0; j--)
                    {
                        fprintf(log_rms_final,"%d - pre \n",pre_amostragem[j]);
                    }

                    fprintf(log_rms_final,"%s","\n");
    /*
                    for(j = 0; j < window_size; j++)
                    {

                        fprintf(log_rms_final,"%d - janela\n",buffer[read1]);
                        read1 = (read1 + 1) % buffer_size;
                    }
    */
                    fprintf(log_rms_final,"%s","\n");

                    //store the 50ms after a event.

                    /*
                    fseek(log_rms_final,save_line - 3,save_line);

                    for(j = 0; j < 5; j++){

                        fgets(str,1024,fp);
                        fprintf(log_rms_final,"%d - pós \n",atoi(str));

                    }
                    */
                }

                soma_quadrado = 0;
                rms = 0;


                read = (read + 1) % buffer_size;
                counter_elements = counter_elements - 2;

            }
            soma_quadrado = 0;
            rms = 0;

        }

    fclose(fp);
    fclose(LOG);
    fclose(log_rms_final);
    return 0;
    }

некоторые комментарии на португальском, но онине имеют отношения к пониманию проблемы.

1 Ответ

2 голосов
/ 21 мая 2019

Я даю вам алгоритм решения здесь.

  1. Всегда записывайте данные 50 мс (или даже 60 мс) в кольцевой буфер.
  2. Если вы обнаружите стартовое событие,
    • Скопировать предыдущие 50 мс из циклического буфера в конечный буфер
    • Продолжить запись полученных данных в конечный буфер в месте 50 мс.
  3. Если вы обнаружите конецсобытие.
    • Продолжить запись в конечный буфер еще на 50 мс.
    • Снова начать запись в кольцевой буфер.
  4. Если у вас есть несколько событий, вам необходимоиметь несколько конечных буферов и может повторять процесс.

Как упоминалось ниже в комментариях, это решение будет работать и для размера окна> 50 мс.Вам необходимо выбрать размер конечного буфера соответственно.

...