过去三天我一直在寻找虫子,我有点放弃了。我已经浏览了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设置
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;
}
}
}
要消化很多,但我真的希望有人可以帮助我 提前谢谢。
答案 0 :(得分:2)
错误是将16位样本传递给float(32bit !!!)vorbis缓冲区,其中我假设float也是16位(doh)
所以分配一个缓冲区
char * data[SAMPLES*2]; // for 16 bit mono samples
并将内容移动到浮动vorbis缓冲区解决了整个问题
vorbisbuffer = vorbis_analysis_buffer(&this->vd,SAMPLES);//still 4410 samples
alcCaptureSamples(mic->pdevice,data,SAMPLES); // move the data to the "data"buffer
for(int i =0;i<SAMPLES;i++){
// make floats out of 16 bit samples
vorbisbuffer[0][i]=((data[i*2+1]<<8)|(0x00ff&(int)data[i*2]))/32768.f;
}
所以对于人类来说如下:
可能听起来过于复杂,但是当去隔行扫描立体声时它非常有意义,这看起来像这样(是的,我从SDK中偷走了这个,但我读到它时根本没有得到它)
vorbisbuffer = vorbis_analysis_buffer(&this->vd,SAMPLES*CHANNELS);
alcCaptureSamples(mic->pdevice,data,SAMPLES); // open al init'ed to stereo16
//where the first dimension is the audio channel and the second the sample index
for(int i =0;i<SAMPLES;i++){
vorbisbuffer[0][i]=((data[i*4+1]<<8)|
(0x00ff&(int)data[i*4]))/32768.f;
vorbisbuffer[1][i]=((data[i*4+3]<<8)|
(0x00ff&(int)data[i*4+2]))/32768.f;
}