音频输出到 .wav 文件是有效的,但是当使用 Vorbis 编码时,它会记录静音吗?
过去三天我一直在寻找错误,但我有点放弃了。我已经研究了 OpenAL SDK 和 Vorbis 示例中的所有示例,但无济于事,所以我希望有人可以帮助我。
问题: 我使用 OpenAL 录制音频,出于调试原因,我将其输出到 C:/out.wav,然后我可以使用选择的任何音频播放器播放它,并播放我录制的任何内容。
我从 openAL 获得的缓冲区与我输入 libvorbisenc 的缓冲区完全相同
(我使用 vorbis_analysis_buffer 请求一个缓冲区并在其上运行 alcCaptureSamples,然后让 vorbis 完成它的工作。)
重点是:为什么 vorbis 将静音返回到我的输出文件以及如何在我的文件中获取有效的压缩音频“C:/out.ogg”?
不要担心一些缺失或多余的括号,它们在复制+粘贴和删除注释中丢失了
代码运行,但它的输出无效。
相关定义等:
//due to strange formatting constraints of this site the's are omitted
define CHANNELS 1
define HERTZ 22050
define BITSPERSAMPLE 16
define BYTESPERSAMPLE 2
define SAMPLES 4410
define SAMPLESIZE 2
define ALIGN (CHANNELS*BITSPERSAMPLE/8)
define BUFFERSIZE (SAMPLES*SAMPLESIZE)
typedef struct
{
char szRIFF[4];
long lRIFFSize;
char szWave[4];
char szFmt[4];
long lFmtSize;
WAVEFORMATEX wfex;
char szData[4];
long lDataSize;
} WAVEHEADER;
class vorbispacker{
public:
vorbispacker();
~vorbispacker();
void consume();
muxer * mux;
// the needed ogg_stream_state is found at this->mux->state;
ogg_page og; /* one Ogg bitstream page. Vorbis packets are inside */
ogg_packet op; /* one raw packet of data for decode */
vorbis_info vi; /* struct that stores all the static vorbis bitstream
settings */
vorbis_comment vc; /* struct that stores all the user comments */
vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
vorbis_block vb; /* local working space for packet->PCM decode */
};
vorbis setup
void vorbispacker::setup(){
this->mux = new muxer;
vorbis_info_init(&this->vi);
int ret = vorbis_encode_init_vbr(&this->vi,CHANNELS,HERTZ,0.7);
vorbis_comment_init(&this->vc);
vorbis_comment_add_tag(&this->vc,"ENCODER","Test");
ret =vorbis_analysis_init(&this->vd,&this->vi);
ret= vorbis_block_init(&this->vd,&this->vb);
iSize=0;
iDataSize=0;
//TEST//
out = fopen("C:/out.wav","wb");
// Prepare a WAVE file header for the captured data
sprintf(swaveheader.szRIFF, "RIFF");
swaveheader.lRIFFSize = 0;
sprintf(swaveheader.szWave, "WAVE");
sprintf(swaveheader.szFmt, "fmt ");
swaveheader.lFmtSize = sizeof(WAVEFORMATEX);
swaveheader.wfex.nChannels = CHANNELS;
swaveheader.wfex.wBitsPerSample = BITSPERSAMPLE;
swaveheader.wfex.wFormatTag = WAVE_FORMAT_PCM;
swaveheader.wfex.nSamplesPerSec = HERTZ;
swaveheader.wfex.nBlockAlign = swaveheader.wfex.nChannels * swaveheader.wfex.wBitsPerSample / 8;
swaveheader.wfex.nAvgBytesPerSec = swaveheader.wfex.nSamplesPerSec * swaveheader.wfex.nBlockAlign;
swaveheader.wfex.cbSize = 0;
sprintf(swaveheader.szData, "data");
swaveheader.lDataSize = 0;
fwrite(&swaveheader, sizeof(WAVEHEADER), 1, out);
srand(time(NULL));
ret = ogg_stream_init(&this->mux->state,rand());
this->eos=0;
ogg_packet header;
ogg_packet header_comm;
ogg_packet header_code;
vorbis_analysis_headerout(&this->vd,&this->vc,&header,&header_comm,&header_code);
ret = ogg_stream_packetin(&this->mux->state,&header);
ret =ogg_stream_packetin(&this->mux->state,&header_comm);
ret =ogg_stream_packetin(&this->mux->state,&header_code);
while(1){
int res = ogg_stream_flush(&this->mux->state,&this->og);
if(!res)break;
this->mux->write(this->og);
}
// this code works great, the headers are correct , and are output to out.ogg
};
有问题的代码:
* // set up buffer*
float ** vorbisbuffer = vorbis_analysis_buffer(&this->vd,SAMPLES);
*// retrieve audio samples ( MONO 16 bit)*
alcCaptureSamples(mic->pdevice,vorbisbuffer[0],SAMPLES);
//this goes to debug .wav file -> the exact same buffer that goes into vorbis
fwrite(vorbisbuffer[0], BUFFERSIZE, 1, out);
iDataSize +=BUFFERSIZE;
int eos =0;
/* tell the library how much we actually submitted */
//SAMPLES is what is inserted into openAL , hence what we put in vorbis
vorbis_analysis_wrote(&vd,SAMPLES);
while(vorbis_analysis_blockout(&this->vd,&this->vb)==1){
/* analysis, assume we want to use bitrate management */
vorbis_analysis(&this->vb,NULL);
vorbis_bitrate_addblock(&this->vb);
while(vorbis_bitrate_flushpacket(&this->vd,&this->op)){
/* weld the packet into the bitstream */
ogg_stream_packetin(&this->mux->state,&op);
/* write out pages (if any) */
while(!eos){
//if result > 0 there are more packets available
int result=ogg_stream_pageout(&this->mux->state,&this->og);
if(result==0)break;
//write ogg page to stream
// since that function outputs the ogg headers OK, i suppose there's no error there.
this->mux->write(this->og);
/* this could be set above, but for illustrative purposes, I do
it here (to show that vorbis does know where the stream ends) */
if(ogg_page_eos(&og))eos=1;
}
}
}
需要消化很多内容,但我真的希望有人可以帮助我。
提前致谢。
I've been hunting bugs for the past three days and I've kind of given up. I've plowed through all the samples in the OpenAL SDK and the Vorbis examples, but to no avail, so I hope someone can help me.
The problem:
I record audio using OpenAL, and for debug reasons i output it to C:/out.wav which i can then play with any audio player of choice and it plays back whatever i recorded.
The exact same buffer i get from openAL is what I input into libvorbisenc
(I request a buffer with vorbis_analysis_buffer and run alcCaptureSamples on it, after which i let vorbis do it's thing.)
The point being : Why is vorbis returning silence to my output file and how do i get valid compressed audio in my file "C:/out.ogg" ?
Don't worry about some missing or extra parentheses , they were lost in the copy+paste and removal of comments
the code runs, but it's output just isn't valid.
Relevant defines etc:
//due to strange formatting constraints of this site the's are omitted
define CHANNELS 1
define HERTZ 22050
define BITSPERSAMPLE 16
define BYTESPERSAMPLE 2
define SAMPLES 4410
define SAMPLESIZE 2
define ALIGN (CHANNELS*BITSPERSAMPLE/8)
define BUFFERSIZE (SAMPLES*SAMPLESIZE)
typedef struct
{
char szRIFF[4];
long lRIFFSize;
char szWave[4];
char szFmt[4];
long lFmtSize;
WAVEFORMATEX wfex;
char szData[4];
long lDataSize;
} WAVEHEADER;
class vorbispacker{
public:
vorbispacker();
~vorbispacker();
void consume();
muxer * mux;
// the needed ogg_stream_state is found at this->mux->state;
ogg_page og; /* one Ogg bitstream page. Vorbis packets are inside */
ogg_packet op; /* one raw packet of data for decode */
vorbis_info vi; /* struct that stores all the static vorbis bitstream
settings */
vorbis_comment vc; /* struct that stores all the user comments */
vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
vorbis_block vb; /* local working space for packet->PCM decode */
};
vorbis setup
void vorbispacker::setup(){
this->mux = new muxer;
vorbis_info_init(&this->vi);
int ret = vorbis_encode_init_vbr(&this->vi,CHANNELS,HERTZ,0.7);
vorbis_comment_init(&this->vc);
vorbis_comment_add_tag(&this->vc,"ENCODER","Test");
ret =vorbis_analysis_init(&this->vd,&this->vi);
ret= vorbis_block_init(&this->vd,&this->vb);
iSize=0;
iDataSize=0;
//TEST//
out = fopen("C:/out.wav","wb");
// Prepare a WAVE file header for the captured data
sprintf(swaveheader.szRIFF, "RIFF");
swaveheader.lRIFFSize = 0;
sprintf(swaveheader.szWave, "WAVE");
sprintf(swaveheader.szFmt, "fmt ");
swaveheader.lFmtSize = sizeof(WAVEFORMATEX);
swaveheader.wfex.nChannels = CHANNELS;
swaveheader.wfex.wBitsPerSample = BITSPERSAMPLE;
swaveheader.wfex.wFormatTag = WAVE_FORMAT_PCM;
swaveheader.wfex.nSamplesPerSec = HERTZ;
swaveheader.wfex.nBlockAlign = swaveheader.wfex.nChannels * swaveheader.wfex.wBitsPerSample / 8;
swaveheader.wfex.nAvgBytesPerSec = swaveheader.wfex.nSamplesPerSec * swaveheader.wfex.nBlockAlign;
swaveheader.wfex.cbSize = 0;
sprintf(swaveheader.szData, "data");
swaveheader.lDataSize = 0;
fwrite(&swaveheader, sizeof(WAVEHEADER), 1, out);
srand(time(NULL));
ret = ogg_stream_init(&this->mux->state,rand());
this->eos=0;
ogg_packet header;
ogg_packet header_comm;
ogg_packet header_code;
vorbis_analysis_headerout(&this->vd,&this->vc,&header,&header_comm,&header_code);
ret = ogg_stream_packetin(&this->mux->state,&header);
ret =ogg_stream_packetin(&this->mux->state,&header_comm);
ret =ogg_stream_packetin(&this->mux->state,&header_code);
while(1){
int res = ogg_stream_flush(&this->mux->state,&this->og);
if(!res)break;
this->mux->write(this->og);
}
// this code works great, the headers are correct , and are output to out.ogg
};
The problematic code:
* // set up buffer*
float ** vorbisbuffer = vorbis_analysis_buffer(&this->vd,SAMPLES);
*// retrieve audio samples ( MONO 16 bit)*
alcCaptureSamples(mic->pdevice,vorbisbuffer[0],SAMPLES);
//this goes to debug .wav file -> the exact same buffer that goes into vorbis
fwrite(vorbisbuffer[0], BUFFERSIZE, 1, out);
iDataSize +=BUFFERSIZE;
int eos =0;
/* tell the library how much we actually submitted */
//SAMPLES is what is inserted into openAL , hence what we put in vorbis
vorbis_analysis_wrote(&vd,SAMPLES);
while(vorbis_analysis_blockout(&this->vd,&this->vb)==1){
/* analysis, assume we want to use bitrate management */
vorbis_analysis(&this->vb,NULL);
vorbis_bitrate_addblock(&this->vb);
while(vorbis_bitrate_flushpacket(&this->vd,&this->op)){
/* weld the packet into the bitstream */
ogg_stream_packetin(&this->mux->state,&op);
/* write out pages (if any) */
while(!eos){
//if result > 0 there are more packets available
int result=ogg_stream_pageout(&this->mux->state,&this->og);
if(result==0)break;
//write ogg page to stream
// since that function outputs the ogg headers OK, i suppose there's no error there.
this->mux->write(this->og);
/* this could be set above, but for illustrative purposes, I do
it here (to show that vorbis does know where the stream ends) */
if(ogg_page_eos(&og))eos=1;
}
}
}
It's a lot to digest, but I really hope someone can help me.
Thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
错误在于将 16 位样本传递到浮点(32 位!!!)vorbis 缓冲区,其中我假设浮点也是 16 位(doh),
因此分配缓冲区
并将内容移至浮点 vorbis 缓冲区解决了整个问题
所以对于人类来说,如下所示:
可能听起来过于复杂,但是当去隔行立体声时它非常有意义,看起来像这样(是的,我从 SDK 中偷了这个,但我根本没有当我读到它时得到它)
The error is in passing 16 bit samples to a float (32bit!!!) vorbis buffer, where i was assuming float was also 16 bit ( doh)
so allocating a buffer
and moving the stuff over to the float vorbis buffer solves the whole thing
so for humans thats as follows:
might sound over-complicated but when de-interlacing stereo it makes perfect sense, which would look like this ( yes i stole this from the SDK's, but i simply didn't get it when i read it)