Функции работы с .WAV файлами

 

  • void* WavOpen(const char *path, SF_INFO *sfinfo);

  • Открывает файл, если он существует, и возвращает указатель на некую структуру SF, который будет использоваться в остальных операциях с .WAV. Если указатель на SF - не NULL, то файл открыт нормально и sfinfo заполняется параметрами файла:

          typedef struct
          {
            DWORD      samplerate ;
            DWORD      samples ;
            DWORD      channels ;
            DWORD      pcmbitwidth ;
            DWORD      format ;
            DWORD      sections ;
            DWORD      seekable ;
    	DWORD	   Reserved[64] ;
          } SF_INFO ;

    Поле "format" образуется путем побитового сложения (OR) двух чисел: формат и его разновидность

         enum
         {    SF_FORMAT_WAV       = 0x10000,       /* Microsoft WAV format (big endian). */
              SF_FORMAT_AIFF      = 0x20000,       /* Apple/SGI AIFF format (little endian). */
              SF_FORMAT_AU        = 0x30000,       /* Sun/NeXT AU format (big endian). */
              SF_FORMAT_AULE      = 0x40000,       /* DEC AU format (little endian). */
              SF_FORMAT_RAW       = 0x50000,       /* RAW PCM data. */
              SF_FORMAT_PAF       = 0x60000,       /* Ensoniq PARIS file format. */
              SF_FORMAT_SVX       = 0x70000,       /* Amiga IFF / SVX8 / SV16 format. */
              
              SF_FORMAT_PCM       = 0x0001,        /* PCM data in 8, 16, 24 or 32 bits. */
              SF_FORMAT_FLOAT     = 0x0002,        /* 32 bit floats. */
              SF_FORMAT_ULAW      = 0x0003,        /* U-Law encoded. */
              SF_FORMAT_ALAW      = 0x0004,        /* A-Law encoded. */
              SF_FORMAT_IMA_ADPCM = 0x0005,        /* IMA ADPCM. */
              SF_FORMAT_MS_ADPCM  = 0x0006,        /* Microsoft ADPCM. */
          
              SF_FORMAT_PCM_BE    = 0x0007,        /* Big endian PCM data. */
              SF_FORMAT_PCM_LE    = 0x0008,        /* Little endian PCM data. */
              SF_FORMAT_PCM_S8    = 0x0009,        /* Signed 8 bit PCM. */
              SF_FORMAT_PCM_U8    = 0x000A,        /* Unsigned 8 bit PCM. */
    
              SF_FORMAT_PCM_BE    = 0x0007,        /* RAW PCM (big endian). */
              SF_FORMAT_PCM_LE    = 0x0008,        /* RAW PCM (little endian). */
              SF_FORMAT_RAW_S8    = 0x0009,        /* Signed 8 bit RAW PCM. */
              SF_FORMAT_RAW_U8    = 0x000A,        /* Unsigned 8 bit RAW PCM. */
              
              SF_FORMAT_SUBMASK   = 0xFFFF,        
              SF_FORMAT_TYPEMASK  = 0x7FFF0000
          } ;

    Честно говоря, я проверял файлы только одного формата: "Microsoft WAV PCM" 16 бит (т.е. обычный WAV), его код - 0x10001 (65537)

     

  • int WavSeek(void* SF, int offset, int whence);

  • Установить текущую позицию файла для чтения. Где offset - смещение (в сэмплах), whence=0 - от начала файла, whence=1 - от текущей позиции

     

  • int WavReadReal(void* SF,double *ptr1,double *ptr2, int items,int normalize);

  • Чтение данных из файла. Где "items" - количество сэмплов, а "double *ptr1" и "double *ptr2" - указатели на массивы переменных типа double, в которые будут загружены данные, раздельно по каналам. Массивы должны быть в состоянии принять указанное количество значений. Если файл одноканальный или ptr2=NULL, то во второй массив ничего не загрузится. Если normalize=1, то считываемые значения нормализуются до максимально-возможного значения для данной разрядности сэмплов ( для 16-битных сэмплов значения ±32767 нормализуются до ±1.0 ), в противном случае - берется целое число, как есть.

    Результат функции - число фактически считанных сэмплов.

     

  • int WavClose(void* SF);

  • Закрыть файл и освободить память, занятую структурой SF


    Функции FFT-преобразования

     

  • void* FFT_start(int size);

  • Подготовить библиотеку для преобразования из действительного значения (Real) в комплексное, указанного размера "size". Полученный указатель (plan) может использоваться многократно.

     

  • int FFT_TransformRealToComplex(void *plan,double *bufREAL,COMPLEX *bufCOMPLEX);

  • Выполняет преобразование по FFT. Следует иметь в виду, что количество элементов в принимаемом буфере должно быть не меньше (size+1)/2. А поскольку COMPLEX состоит из двух чисел типа double, то для четного "size" размеры буферов могут быть одинаковы, и не менее чем sizeof(double)*size.

     

  • void* FFT_stop(void *plan);

  • Освободить память, занимаемую структурой plan

     


    Вспомогательные функции

  • void CalcComplexABS(COMPLEX *bufCOMPLEX,double *bufREAL,int size);
    void CalcComplexARG(COMPLEX *bufCOMPLEX,double *bufREAL,int size);

  • Получить из комплексного числа действителных значений амплитуды (ABS) и угла (ARG)
    Где

    abs(z) =sqrt(z.x * z.x + z.y * z.y)
    arg(z) = atan(z.y/z.x) или arg(z) = atan2(z.y,z.x)

    Следует иметь ввиду, что количество элементов в комплексном и действительном представлении одинаково, но размер элемента - разный. Буфер действительных значений bufREAL должен быть способен принять указанное количестов элементов типа double, т.е. его размер не меньше sizeof(double)*size.

     

  • void WinHamming(double *bufREAL,int size);
    void WinHanning(double *bufREAL,int size);
    void WinWelch(double *bufREAL,int size);
    void WinTriangular(double *bufREAL,int size);

  • Наложение оконных функций типа: Hamming, Hanning, Welch и Bartlett (Triangular), соответственно.

    Примечание: Результат FFT-преобразования без использования оконных функций практически идентичен Спектралабовскому "Uniform". А с использованием указанных функций - результат почти в два раза меньше. Причину я пока не понял.


    Для функций работы с .WAV файлами использована библиотека libsndfile http://www.zip.com.au/~erikd/libsndfile/.

    Для функций FFT-преобразования использована библиотека FFTW http://www.fftw.org/.

    Остальные функции написаны мной. Описания оконных функций почерпнуты мной из разных источников, но окончательно я использовал http://astronomy.swin.edu.au/pbourke/analysis/windows/

    Если возникнут вопросы, пишите мне: mailto:ant@kmbank.kuban.ru
    Анатолий