2

私は過去 3 日間、虫を探していましたが、ちょっとあきらめました。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;
        }
      }
    }

消化するのは大変ですが、誰かが私を助けてくれることを本当に願っています.
前もって感謝します。

4

1 に答える 1

2

エラーは、16ビットサンプルをfloat(32ビット!!!)vorbisバッファーに渡すことです。ここで、floatも16ビット(doh)であると想定していました。

バッファを割り当てる

char * data[SAMPLES*2]; // for 16 bit mono samples

ものをfloatvorbisバッファーに移動すると、すべてが解決されます

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; 
}

したがって、人間の場合、次のようになります。

  • サンプルの右バイトを取得し、32ビットバッファで左に8ビットシフトします
  • サンプルの左側のバイトを取得し、バッファーを使用してAND演算子を実行します
  • 全体を16ビット左にシフトします(/ 32768)(最下位バイトが最初)

複雑すぎるように聞こえるかもしれませんが、ステレオをインターレース解除すると、次のようになります(はい、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;  
}
于 2010-07-17T14:28:38.363 に答える