C++ 使用C+;中的libsndfile从WAV文件中提取原始音频数据+;
我正在开发一个应用程序,它将为某些设备提供音频输入。该设备期望以原始音频数据流(16位,48kHz)的形式提供音频输入。因此,无论WAV文件中音频数据的格式如何(8位、16位、24位、32位等),我都希望从WAV文件中提取原始音频数据。为此,我计划使用libsndFile库。我修改了LbSNDFrm的C++示例代码,如下所示:C++ 使用C+;中的libsndfile从WAV文件中提取原始音频数据+;,c++,audio,wav,libsndfile,C++,Audio,Wav,Libsndfile,我正在开发一个应用程序,它将为某些设备提供音频输入。该设备期望以原始音频数据流(16位,48kHz)的形式提供音频输入。因此,无论WAV文件中音频数据的格式如何(8位、16位、24位、32位等),我都希望从WAV文件中提取原始音频数据。为此,我计划使用libsndFile库。我修改了LbSNDFrm的C++示例代码,如下所示: #include "stdafx.h" #include <sndfile.hh> static void create_file (const char
#include "stdafx.h"
#include <sndfile.hh>
static void create_file (const char * fname, int format, const short* buffer,const unsigned int& len)
{
// file ;
int channels = 1 ; //A Mono wave file.
int srate = 48000 ;
printf ("Creating file named '%s'\n", fname) ;
SndfileHandle file = SndfileHandle (fname, SFM_WRITE, format, channels, srate) ;
int x = file.write (buffer, len) ;
}
static void read_file (const char * fname)
{
SndfileHandle file ;
file = SndfileHandle (fname) ;
const unsigned int uiBuffLen = file.channels() * file.frames();
short* data = new short [uiBuffLen] ;
memset(data,0x00,uiBuffLen);
int x = file.command(SFC_SET_SCALE_FLOAT_INT_READ, (void*)data, uiBuffLen);
file.read (data, uiBuffLen) ; //Read the audio data in the form of 16 bit short integer
//Now create a new wave file with audio data in the form of 16 bit short integers
create_file ("ConvertedFile.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_16,data, (const unsigned int&)uiBuffLen) ;
//Now fill a buffer containing audio data and dump it into a file so that the same can be fed to a device expecting the raw audio data
unsigned char* bytBuffer = new unsigned char[uiBuffLen*2];
memset(bytBuffer, 0x00, uiBuffLen*2);
file.readRaw(bytBuffer, uiBuffLen*2);
FILE * pFile;
pFile = fopen ("RawAudio.dat","w");
if (pFile!=NULL)
{
fwrite(bytBuffer, 1, uiBuffLen*2, pFile);
fclose (pFile);
}
delete [] data;
delete [] bytBuffer;
}
int _tmain(int argc, _TCHAR* argv[])
{
//The sample file is a Mono file containing audio data in float format.
const char * fname = "MonoWavFile.wav" ;
read_file (fname) ;
return 0;
}
#包括“stdafx.h”
#包括
静态void create_文件(const char*fname、int格式、const short*buffer、const unsigned int&len)
{
//档案;
int channels=1;//一个单波文件。
int srate=48000;
printf(“正在创建名为“%s”\n,fname)的文件);
SndfileHandle file=SndfileHandle(fname,SFM_WRITE,format,channels,srate);
int x=file.write(缓冲区,len);
}
静态无效读取文件(const char*fname)
{
SndfileHandle文件;
file=SndfileHandle(fname);
const unsigned int uiBuffLen=file.channels()*file.frames();
短*数据=新短[uiBuffLen];
memset(数据,0x00,uiBuffLen);
int x=file.command(SFC\u SET\u SCALE\u FLOAT\u int\u READ,(void*)数据,uiBuffLen);
file.read(data,uiBuffLen);//读取16位短整数形式的音频数据
//现在创建一个新的wave文件,其中包含16位短整数形式的音频数据
创建_文件(“ConvertedFile.wav”,SF_格式_wav | SF_格式_PCM_16,数据,(常量unsigned int&)uiBuffLen);
//现在填充一个包含音频数据的缓冲区,并将其转储到一个文件中,这样就可以将该缓冲区提供给需要原始音频数据的设备
unsigned char*bytBuffer=新的unsigned char[uiBuffLen*2];
memset(bytBuffer,0x00,uiBuffLen*2);
readRaw(bytBuffer,uiBuffLen*2);
文件*pFile;
pFile=fopen(“RawAudio.dat”,“w”);
if(pFile!=NULL)
{
fwrite(bytBuffer,1,uiBuffLen*2,pFile);
fclose(pFile);
}
删除[]数据;
删除[]bytBuffer;
}
int _tmain(int argc,_TCHAR*argv[]
{
//示例文件是一个单声道文件,包含浮点格式的音频数据。
const char*fname=“monovavfile.wav”;
读取文件(fname);
返回0;
}
嗯,上面的代码可能看起来很糟糕,但我现在只是在寻找想法。我使用一个文件“monowavile.wav”,它是一个单波文件,具有32位浮点值形式的音频数据。
我使用libsndfile库创建了一个新文件“ConvertedFile.wav”。此文件具有16位PCM格式的音频数据。我在媒体播放器中播放这个文件,我发现转换已经正确完成
然后,我创建另一个文件“RawAudio.dat”来只保存音频数据,我可以使用它将音频输入提供给设备。文件已创建,当我将其发送到设备时,音频根本不正确。这表明我做错了一件可怕的事。谁能告诉我我做错了什么?我以前从未做过类似的工作,因此如果能得到任何帮助,我将不胜感激。我使用了
sf\u open\u virtual
。
我用sf\u open\u virtual
制作了另一个缓冲区。然后我使用这个“另一个缓冲区”来提供RTP数据包。
所以我想这就是你需要的
我有问题,使它从RTP包到文件的其他方向
//============================================================================
// Name : libsndfile_demo.cpp
// Author :
// Version :
// Copyright : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================
#include <iostream>
#include <string.h>
#include "sndfile.h"
#include <assert.h>
#include <unistd.h>
using namespace std;
typedef struct
{ sf_count_t offset, length ;
unsigned char data [160] ;
} VIO_DATA ;
FILE *checker;
const void* old_ptr = NULL;
static sf_count_t vfget_filelen (void *user_data)
{
VIO_DATA *vf = (VIO_DATA *) user_data ;
return vf->length ;
} /* vfget_filelen */
static sf_count_t vfseek (sf_count_t offset, int whence, void *user_data)
{
VIO_DATA *vf = (VIO_DATA *) user_data ;
switch (whence)
{ case SEEK_SET :
vf->offset = offset ;
break ;
case SEEK_CUR :
vf->offset = vf->offset + offset ;
break ;
case SEEK_END :
vf->offset = vf->length + offset ;
break ;
default :
break ;
} ;
return vf->offset ;
} /* vfseek */
static sf_count_t vfread (void *ptr, sf_count_t count, void *user_data)
{
VIO_DATA *vf = (VIO_DATA *) user_data ;
/*
** This will brack badly for files over 2Gig in length, but
** is sufficient for testing.
*/
if (vf->offset + count > vf->length)
count = vf->length - vf->offset ;
memcpy (ptr, vf->data + vf->offset, count) ;
vf->offset += count ;
return count ;
} /* vfread */
static sf_count_t vfwrite (const void *ptr, sf_count_t count, void *user_data)
{
static int skip = 0;
//TODO: Why this is working ?!?!?!
if (skip < 1)
{
skip++;
return count;
}
//SendTo RTP packetizer instead of writing to file
fwrite(ptr, count, 1, checker);
return count ;
} /* vfwrite */
static sf_count_t vftell (void *user_data)
{
VIO_DATA *vf = (VIO_DATA *) user_data ;
return vf->offset ;
} /* vftell */
int main()
{
SF_INFO writing_sfinfo;
writing_sfinfo.channels = 1;
writing_sfinfo.format = SF_FORMAT_WAV | SF_FORMAT_GSM610;
writing_sfinfo.samplerate = 8000;
assert(true == sf_format_check(&writing_sfinfo));
SF_INFO reading_sfinfo;
memset(&reading_sfinfo, 0, sizeof(reading_sfinfo));
SNDFILE *input = sf_open("/home/georgi/Downloads/thank_you_60.PCMA", SFM_READ, &reading_sfinfo);
checker = fopen("/home/georgi/Downloads/checker.wav", "w+");
short file_data[reading_sfinfo.channels * 160];
int read_frames = 0;
SF_VIRTUAL_IO vio ;
// Set up pointers to the locally defined functions.
vio.get_filelen = vfget_filelen ;
vio.seek = vfseek ;
vio.read = vfread ;
vio.write = vfwrite ;
vio.tell = vftell ;
VIO_DATA vio_data ;
// Set virtual file offset and length to zero.
vio_data.offset = 0 ;
vio_data.length = 0 ;
SNDFILE *virt_file = sf_open_virtual (&vio, SFM_WRITE, &writing_sfinfo, &vio_data);
int old_length = 0;
while ((read_frames = sf_readf_short(input, file_data, 160)))
{
sf_writef_short(virt_file, file_data, read_frames);
}
sf_close(virt_file);
sf_close(input);
fclose(checker);
return 0;
}
//============================================================================
//名称:libsndfile_demo.cpp
//作者:
//版本:
//版权:您的版权声明
/ C++:ANSI风格的Hello World
//============================================================================
#包括
#包括
#包括“sndfile.h”
#包括
#包括
使用名称空间std;
类型定义结构
{sf_count_t offset,长度;
无符号字符数据[160];
}VIO_数据;
档案检查;
const void*old_ptr=NULL;
静态sf_计数vfget_文件长度(无效*用户数据)
{
VIO_数据*vf=(VIO_数据*)用户_数据;
返回vf->length;
}/*vfget_filelen*/
静态sf_计数vfsek(sf_计数vfsek偏移量、int whence、void*用户数据)
{
VIO_数据*vf=(VIO_数据*)用户_数据;
开关(从何处)
{case SEEK_集:
vf->offset=偏移量;
打破
个案查询:
vf->offset=vf->offset+offset;
打破
案件结束:
vf->offset=vf->length+offset;
打破
违约:
打破
} ;
返回vf->offset;
}/*vfseek*/
静态sf_计数vfread(无效*ptr、sf_计数、无效*用户数据)
{
VIO_数据*vf=(VIO_数据*)用户_数据;
/*
**对于长度超过2Gig的文件,这将非常糟糕,但是
**足够进行测试。
*/
如果(vf->偏移+计数>vf->长度)
计数=vf->length-vf->offset;
memcpy(ptr,vf->data+vf->offset,count);
vf->offset+=计数;
返回计数;
}/*vfread*/
静态sf_计数vfwrite(常量无效*ptr、sf_计数、无效*用户数据)
{
静态int skip=0;
//托多:这为什么有效?!?!?!
如果(跳过<1)
{
skip++;
返回计数;
}
//发送到RTP打包器,而不是写入文件
写入(ptr、计数、1、校验);
返回计数;
}/*vfwrite*/
静态sf_计数vftell(无效*用户数据)
{
VIO_数据*vf=(VIO_数据*)用户_数据;
返回vf->offset;
}/*vftell*/
int main()
{
SF_信息写入_sfinfo;
写入_sfinfo.channels=1;
写入_sfinfo.format=SF_format_WAV | SF_format_GSM610;
写入_sfinfo.samplerate=8000;
断言(true==sf_格式检查(&writing_sfinfo));
SF_信息读取_sfinfo;
memset(&reading_sfinfo,0,sizeof(reading_sfinfo));
SNDFILE*input=sf_open(“/home/georgi/Downloads/thank_you_60.PCMA”、SFM_READ和reading_sfinfo);
checker=fopen(“/home/georgi/Downloads/checker.wav”,“w+”);
短文件\u数据[正在读取\u sfinfo.chan