【问题标题】:Segmentation fault and wav file reader分段错误和 wav 文件阅读器
【发布时间】:2016-10-13 08:10:01
【问题描述】:

我决定在音频算法上玩 C++,更习惯于 Matlab 我有点挣扎。

第一步是使用 sndfile 库将 wav 文件记录到数组中。 我使用了库中的示例:

https://github.com/michaelwu/libsndfile/blob/master/examples/sfprocess.c

我想创建一个 wavF 类,其中包含 wav 的一般信息(采样频率、通道...)和 wav 文件的数据以供进一步处理。

我几乎实现了这一点,但是当进入 wavfile.cpp 中的while ((readcount = sf_read_double (infile, data, BUFFER_LEN))) 循环(但并非总是如此)时会出现分段错误。我不知道为什么。

我想将 wav 数据保存在数组 double* m_wavData 中,使用带有缓冲区循环的类构造函数中的函数 process_data。

这是他的代码:

主要:

#include    <sndfile.h>
#include    <stdio.h>
#include    "wavfile.h"


int main (void)
{
    SNDFILE      *infile ;
    const char  *infilename = "Piano_mf_Gb2.wav" ;
    SndfileHandle file;
    file=SndfileHandle(infilename);

    int test(initwav(infile, file, infilename));
    if(test==1) return 0 ;

    wavF wav1(infile, file, infilename);

    sf_close (infile) ;
    /* Close input and output files. */


    return 0 ;
} /* main */

标题:

    #ifndef WAVFILE_H_INCLUDED
#define WAVFILE_H_INCLUDED

#define BUFFER_LEN  1024
#include    <sndfile.hh>

class wavF
{
    public:
    wavF(SNDFILE  *infile, SndfileHandle file,const char * fName);
    wavF(const unsigned int wavsize,const unsigned int channels,const unsigned int samplerate,const char * fileName);
    ~wavF();

    protected:
         const unsigned int m_wavsize;
         const unsigned int m_channels;
         const unsigned int m_samplerate;

        const char * m_fileName;
        double * m_wavData;

};
static void process_data (double *wavData, double * data, int count, int channels);
int initwav(SNDFILE  *infile,SndfileHandle file,const char * fName);
#endif // WAVFILE_H_INCLUDED

和代码 wavfile.cpp

   #include "wavfile.h"

wavF::wavF(SNDFILE  *infile, SndfileHandle file,const char * fName): m_channels(file.channels()),m_samplerate(file.samplerate()),m_wavsize(file.frames()),m_fileName(fName)
{
     /* This is a buffer of double precision floating point values
    ** which will hold our data while we process it.
    */
    static double data [BUFFER_LEN] ;
    //initialise class array
    double* m_wavData = new double[m_wavsize*m_channels] ;


    printf ("Opened file '%s'\n", m_fileName) ;
    printf ("Sample rate : %d\n", m_samplerate) ;
    printf ("Channels    : %d\n", m_channels) ;
    printf ("Size    : %d\n", m_wavsize) ;

    puts ("") ;

    //fill array with the wav channel
    int readcount(0);
    int counter(0);
    while ((readcount = sf_read_double (infile, data, BUFFER_LEN)))
    {
     //  printf("%i \n",counter);
      // counter++;
       process_data (m_wavData,data, readcount, m_channels) ;
    } ;

  /* RAII takes care of destroying SndfileHandle object. */
} /* read_file */

wavF::wavF(const unsigned int wavsize,const unsigned int channels,const unsigned int samplerate,const char * fileName):
m_channels(channels),m_samplerate(samplerate),m_wavsize(wavsize),m_fileName(fileName)
{
}

static void process_data (double *m_wavData,double *data, int count, int channels)
{
    int k;

    /* Process the data here.
    ** If the soundfile contains more then 1 channel you need to take care of
    ** the data interleaving youself.
    */

    for (k = 0 ; k < channels*count ; k ++)
            m_wavData [k] = data[k] ;
} /* process_data */

wavF::~wavF()
{
    delete  m_wavData;
    printf("array is detroyed");
}

int initwav(SNDFILE  *infile,SndfileHandle file, const char * fName)
{

    SF_INFO     sfinfo ;
        if (! (infile = sf_open (fName, SFM_READ, &sfinfo)))
    {   /* Open failed so print an error message. */
        printf ("Not able to open input file %s.\n", fName) ;
        puts (sf_strerror (NULL)) ;
        return 1;
    } ;
    return 0;
}

我写了什么异端代码?有什么建议吗?

(在 uiowa.edu 数据库中找到的音频 wav) 谢谢。

【问题讨论】:

  • 调试器是解决此类问题的正确工具。 询问 Stack Overflow 之前,您应该逐行逐行检查您的代码。如需更多帮助,请阅读How to debug small programs (by Eric Lippert)。至少,您应该 [编辑] 您的问题,以包含一个重现您的问题的 Minimal, Complete, and Verifiable 示例,以及您在调试器中所做的观察。
  • 我正在使用 code::blocks,问题是当我使用调试器时没有错误,只有当我构建和运行时。我会做一个更简单的
  • 您可能会将调试器与编译器混淆。调试器可用于在设置断点的情况下运行您的程序,并逐行执行代码。您可以在每一步之后查看当前变量值。
  • 仅供参考,double* m_wavData = ... 在您的构造函数主体中隐藏成员变量double* m_wavData,使该成员完全未初始化(它也不会出现在您的成员初始化器列表中)。我真诚地怀疑你是否打算这样做。
  • initwav 中,您将分配给参数infile。这对您传递其值的变量没有影响。

标签: c++ audio wav


【解决方案1】:

谢谢大家! 他们有几个错误: 1) 正如 Jean-François Fabre 所指出的,缓冲区大小不正确,导致尝试在数组m_wavData 中写入数据,从包含 wav 值data 的数组中取出值。 ---> m_wavData = new double[m_wavsize*m_channels] ;

2) 正如 WhozCraig 所指出的,我在类的构造函数中重新声明了变量m_wavData,从而导致隐藏了同名的成员变量。 --> 删除重新声明。

3) 正如 molbdnilo 所指出的,参数infile 在我使用它的方式中没有添加任何效果,导致不读取 wav 数据。 --> 通过在 init 和构造函数中打开来解决问题。

4) 我一直在写数组m_wavData(缓冲区大小)的相同情况。 --> 在好的情况下添加了计数器。

这是我的解决方案在一个更小的版本中(πάντα ῥεῖ):

#include    <sndfile.h>
#include    <stdio.h>
#define BUFFER_LEN  1024
#include    <sndfile.hh>
class wavF
{
    public:
    wavF(SNDFILE  *infile, SndfileHandle file,const char * fName);
    void prinvalue(int k);// help to see if the values are good
    ~wavF();

    protected:
          unsigned int m_wavsize;
          unsigned int m_channels;
          unsigned int m_samplerate;

        const char * m_fileName;
        double * m_wavData;

};

int main(void)
{
    // initiate variables to open the file
    SNDFILE     *infile ;
    const char  *infilename = "test.wav" ;
    SndfileHandle file;
    file=SndfileHandle(infilename);

        SF_INFO     sfinfo ;
        if (! (infile = sf_open (infilename, SFM_READ, &sfinfo)))
    {   /* Open failed so print an error message. */
        printf ("Not able to open input file %s.\n", infilename) ;
        puts (sf_strerror (NULL)) ;
        return 1;
    } ;

    wavF wav1(infile, file, infilename);
    wav1.prinvalue(1000);//test if the value inside of the wav is correct

    sf_close (infile);
    /* Close input and output files. */


    return 0 ;
}

void wavF::prinvalue(int k)
{
    printf("the value is %lf",m_wavData[k]);
}

wavF::wavF(SNDFILE  *infile, SndfileHandle file,const char * fName):m_channels(file.channels()),m_samplerate(file.samplerate()),m_wavsize(file.frames()),m_fileName(fName)
{   //declaration of the allocated arrays
    static double* data= new double [BUFFER_LEN*m_channels] ;
    m_wavData = new double[m_wavsize*m_channels] ;

    printf ("Opened file '%s'\n", m_fileName) ;
    printf ("Sample rate : %d\n", m_samplerate) ;
    printf ("Channels    : %d\n", m_channels) ;
    printf ("Size    : %d\n", m_wavsize) ;
    puts ("") ;

    int readcount(0);//number of data in the buffer
    int counter(0);// number of time buffer is used
    while ((readcount = sf_read_double (infile, data, BUFFER_LEN*m_channels)))
    {
        int k;
        for (k = 0; k < readcount ; k ++)
        {
             m_wavData[counter*readcount+k] = data[k] ;//put data in the array
        }
        counter++;
        printf("the wav value is %lf \n",m_wavData[counter*readcount-1]);//look if the stored values are good
    } ;
    delete[] data; //clear allocated buffer array
} /* read_file */


wavF::~wavF()
{
    delete[] m_wavData;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-19
    • 2013-03-15
    • 1970-01-01
    • 1970-01-01
    • 2021-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多