OSX上的Libsndfile会破坏数据

时间:2015-11-03 12:04:01

标签: macos valgrind libsndfile

我遇到了在OSX上制作基于Libsndfile的音频应用程序的奇怪问题。读取和写入缓冲区中的数据以奇怪和不可预测的方式被破坏。

这是一个简短的程序,可以为我重现问题:

#include <iostream>
#include "sndfile.h"

int main(int argc, const char * argv[])
{
float* buffer = (float*)malloc(4096*sizeof(float));
SNDFILE* file;
SF_INFO infos;
infos.format = 0;
file = sf_open("ABCD.WAV",SFM_READ,&infos);
if (file==NULL)
{
    std::cout << "LIBSNDFILE ERROR: " << sf_strerror(file) << "\n";   
}

int samplesread=1;
while (samplesread!=0)
    {
        samplesread = sf_readf_float(file,buffer,4096);
        std::cout << " " << samplesread;
    }
std::cout << "";
sf_close(file);
free(buffer);
return 0;
}

程序编译并运行正常,但使用Valgrind运行它会发现这种错误:

==933== Invalid write of size 8 
==933==    at 0x56EF4B: _platform_bzero$VARIANT$Merom (in    /usr/lib/system/libsystem_platform.dylib)
==933==    by 0x2FDBB: psf_memset (in /opt/local/lib/libsndfile.1.dylib)
==933==    by 0x11E0B: sf_readf_float (in /opt/local/lib/libsndfile.1.dylib)
==933==    by 0x100001323: main (in ./sndfiletest)
==933==  Address 0x873270 is 0 bytes after a block of size 16,384 alloc'd
==933==    at 0x4711: malloc (vg_replace_malloc.c:296)
==933==    by 0x100001287: main (in ./sndfiletest

提前感谢您的帮助 -T

2 个答案:

答案 0 :(得分:0)

您的wav文件可能是立体声。那么你的缓冲区大小需要是4096 * 2

答案 1 :(得分:0)

您的代码存在的问题是,它仅适用于单声道输入文件。

根据frames,您需要熟悉框架的概念:

  

对于frames-count函数,frames参数指定帧数。一帧只是一个样本块,每个通道一个。必须注意确保ptr指向的数组中有足够的空间,以容纳(帧*通道)数量的项目(短裤,整数,浮点数或双打)。

通过将函数sf_readf_float与第三个参数4096一起使用,您要求读取4096个。一帧是一个样本乘以通道数C。所以当你这样做

sf_readf_float(file,buffer,4096);

您要将4096*C个样本存储到您声明为

的缓冲区中
float* buffer = (float*)malloc(4096*sizeof(float));

您溢出了缓冲区!

要解决此问题,您有两种选择。

1。继续使用sf_readf_float并修正buffer

的分配
#include <stdlib.h>
#include <iostream>
#include "sndfile.h"

int main(int argc, const char * argv[])
{
  float* buffer;
  SNDFILE* file;
  SF_INFO infos;
  file = sf_open("inFile.wav",SFM_READ,&infos);

  buffer = (float*)malloc(infos.channels*4096*sizeof(float));

  if (file==NULL)
  {
    std::cout << "LIBSNDFILE ERROR: " << sf_strerror(file) << "\n";
  }

  int samplesread=1;
  while (samplesread!=0)
  {
    samplesread = sf_readf_float(file,buffer,4096);
    std::cout << " " << samplesread;
  }
  std::cout << "";

  sf_close(file);
  free(buffer);
  return 0;
}

2。保持缓冲区分配并使用sf_read_float

我不建议这样做,因为您仍然需要检查4096是否为C的倍数。对于立体声输入,您可以:

#include <stdlib.h>
#include <iostream>
#include "sndfile.h"

int main(int argc, const char * argv[])
{
  float* buffer = (float*)malloc(4096*sizeof(float));
  SNDFILE* file;
  SF_INFO infos;
  file = sf_open("inFile.wav",SFM_READ,&infos);

  if (file==NULL)
  {
    std::cout << "LIBSNDFILE ERROR: " << sf_strerror(file) << "\n";
  }

  int samplesread=1;
  while (samplesread!=0)
  {
    samplesread = sf_read_float(file,buffer,4096);
    std::cout << " " << samplesread;
  }
  std::cout << "";

  sf_close(file);
  free(buffer);
  return 0;
}