当前位置:编程学习 > C/C++ >>

libsndfile 用法简介

最近要做些声学信号检测方面的工作。需要对一些 wav 格式的文件进行分析处理。google 了一番,发现了 libsndfile。libsndfile 是一个 C 语言写成的 开放源代码的音频文件读写的库。可以读写 WAV 格式,FLAC 格式和其他许多常见格式(因为专利原因不支持MP3)。LGPL 协议。

libsndfile 的用法很简单。


[cpp]
SNDFILE* sf_open(const char *path, int mode, SF_INFO *sfinfo); 

SNDFILE* sf_open(const char *path, int mode, SF_INFO *sfinfo);用来打开一个音频文件。 mode 有三个选项。
SFM_READ    - read only mode
SFM_WRITE   - write only mode
SFM_RDWR    - read/write mode

音频文件的一些基本信息由 sfinfo 来返回。


[cpp]
typedef struct 
{   sf_count_t  frames ;     /* Used to be called samples. */ 
    int         samplerate ; 
    int         channels ; 
    int         format ; 
    int         sections ; 
    int         seekable ; 
} SF_INFO ; 

typedef struct
{   sf_count_t  frames ;     /* Used to be called samples. */
    int         samplerate ;
    int         channels ;
    int         format ;
    int         sections ;
    int         seekable ;
} SF_INFO ;需要注意的是,如果是SFM_READ 模式打开一个文件, sfinfo 的 format 字段应预先写为 0 。
打开音频文件后,测试 format 的各个字段就能知道音频文件的基本类型。
[cpp]
sf_count_t sf_seek(SNDFILE *sndfile, sf_count_t frames, int whence); 

sf_count_t sf_seek(SNDFILE *sndfile, sf_count_t frames, int whence);用来在音频文件的数据区中移动文件指针,有点像 lseek 函数。不过sf_seek 函数自动的屏蔽了非数据区的部分。所有的移动都是在数据区中进行了,而且是以数据帧为单位,相当的方便。


[cpp]
sf_count_t  sf_read_short   (SNDFILE *sndfile, short *ptr, sf_count_t items) ; 
sf_count_t  sf_read_int     (SNDFILE *sndfile, int *ptr, sf_count_t items) ; 
sf_count_t  sf_read_float   (SNDFILE *sndfile, float *ptr, sf_count_t items) ; 
sf_count_t  sf_read_double  (SNDFILE *sndfile, double *ptr, sf_count_t items) ; 
sf_count_t  sf_readf_short   (SNDFILE *sndfile, short *ptr, sf_count_t frames) ; 
sf_count_t  sf_readf_int     (SNDFILE *sndfile, int *ptr, sf_count_t frames) ; 
sf_count_t  sf_readf_float   (SNDFILE *sndfile, float *ptr, sf_count_t frames) ; 
sf_count_t  sf_readf_double  (SNDFILE *sndfile, double *ptr, sf_count_t frames) ; 

sf_count_t  sf_read_short   (SNDFILE *sndfile, short *ptr, sf_count_t items) ;
sf_count_t  sf_read_int     (SNDFILE *sndfile, int *ptr, sf_count_t items) ;
sf_count_t  sf_read_float   (SNDFILE *sndfile, float *ptr, sf_count_t items) ;
sf_count_t  sf_read_double  (SNDFILE *sndfile, double *ptr, sf_count_t items) ;
sf_count_t  sf_readf_short   (SNDFILE *sndfile, short *ptr, sf_count_t frames) ;
sf_count_t  sf_readf_int     (SNDFILE *sndfile, int *ptr, sf_count_t frames) ;
sf_count_t  sf_readf_float   (SNDFILE *sndfile, float *ptr, sf_count_t frames) ;
sf_count_t  sf_readf_double  (SNDFILE *sndfile, double *ptr, sf_count_t frames) ;
上面 8 个函数用来从音频文件中读取数据。 这里来说一说 items 和 frames 的区别。
对于单声道的音频文件。 item 和 frame 是一样的。 一个 item 对应一个数据点。
对于多声道音频文件,一个 frame 包含多个数据点,比如双声道音频文件,一个 frame 包括 2 个 item。
另外,音频文件中可能用 8 bits 来存储一个数据点,也可能是 16bits,可能用整数也可能用浮点数来存储音频数据。sf_read_XXX 系列函数会替你完成数据的转换工作。
下面是一个简单的例子,读取一个音频文件,显示其基本信息,并将数据存储到文本文件中。 这里假设音频文件为单声道。
[cpp]
#include    <stdio.h>  
#include    <stdlib.h>  
#include    <sndfile.h>  
 
void save(short *b1, double *b2, int n); 
int main(int argc, char * argv[]) 

    SF_INFO sf_info; 
    SNDFILE *snd_file; 
    short *buf1; 
    double *buf2; 
    if(argc != 2) 
    { 
        exit(1); 
    } 
    sf_info.format = 0; 
    snd_file = sf_open(argv[1], SFM_READ, &sf_info) ; 
    printf ("Using %s.\n", sf_version_string ()) ; 
    printf("File Name : %s\n", argv[1]); 
    printf("Sample Rate : %d\n", sf_info.samplerate); 
    printf("Channels : %d\n", sf_info.channels); 
    printf("Sections  : %d\n", sf_info.sections ); 
    printf("Frames   : %d\n", (int)sf_info.frames  ); 
 
    buf1 = (short *)malloc(sf_info.frames *sizeof(short)); 
    buf2 = (double *)malloc(sf_info.frames *sizeof(double)); 
    sf_readf_short(snd_file, buf1, sf_info.frames) ; 
    sf_seek  (snd_file, 0, SEEK_SET) ; 
    sf_readf_double(snd_file, buf2, sf_info.frames) ; 
    save(buf1, buf2, sf_info.frames); 
    free(buf1); 
    free(buf2); 
    sf_close(snd_file); 
    return 0; 

 
void save(short *b1, double *b2, int n) 

    int i; 
    FILE *fp1; 
    FILE *fp2; 
    fp1 = fopen("short.dat", "w"); 
    fp2 = fopen("double.dat", "w"); 
    for(i = 0; i< n; i++) 
    { 
            fprintf(fp1, "%d\n", (int)b1[i]); 
            fprintf(fp2, "%f\n", b2[i]); 
    } 
    fclose(fp1); 
    fclose(fp2); 

#include <stdio.h>
#include <stdlib.h>
#include <sndfile.h>

void save(short *b1, double *b2, int n);
int main(int argc, char * argv[])
{
    SF_INFO sf_info;
    SNDFILE *snd_file;
    short *buf1;
    double *buf2;
    if(argc != 2)
    {
    &nb

补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,