//________________________________________________
//   Init lame encoder
// frequence    : Impose frequency , 0 means reuse the incoming fq
// mode                         : ADM_STEREO etc...
// bitrate              : Bitrate in kbps (96,192...)
// return 0 : init failed
//                              1 : init succeeded
//_______________________________________________
uint8_t AUDMEncoder_Vorbis::init(ADM_audioEncoderDescriptor *config)
{
  int ret;
  VORBIS_encoderParam *vorbisConf=(VORBIS_encoderParam *)config->param;
  ADM_assert(config->paramSize==sizeof(VORBIS_encoderParam));

  ogg_packet header1,header2,header3;
  int err;

  
  
  vorbis_info_init(&VI) ;

  switch(vorbisConf->mode)
  {
    
    case ADM_VORBIS_VBR:
                      err=vorbis_encode_init(&VI,
                              _wavheader->channels,
                              _wavheader->frequency,
                              -1, // Max bitrate      
                              config->bitrate*1000, //long nominal_bitrate,
                              -1 //long min_bitrate))
                            );
                      break;
    case  ADM_VORBIS_QUALITY :
                    err=vorbis_encode_init_vbr(&VI,
                                _wavheader->channels,
                                _wavheader->frequency,
                                vorbisConf->quality/10
                              );
                    break;
      
    default:
      ADM_assert(0);
  }
  if (err!=0) 
  {
	  delete (vorbisStruct*)_handle;
	  _handle = NULL;

    printf("[vorbis] init error %d\n",err);
    return 0;
  }
  vorbis_analysis_init(&VD, &VI) ;
  vorbis_block_init(&VD, &VB);
  vorbis_comment_init(&VC);
  vorbis_comment_add_tag(&VC, "encoder", "AVIDEMUX2") ;

  vorbis_analysis_headerout(&VD, &VC, &header1,
                             &header2, &header3);


// Store all headers as extra data
// see ogg vorbis decode for details
// we need 3 packets

  _extraSize=header1.bytes+header2.bytes+header3.bytes+3*sizeof(uint32_t);
  _extraData=new uint8_t[_extraSize];

  uint32_t *ex=(uint32_t *)_extraData;
  uint8_t *d;
  d=_extraData+sizeof(uint32_t)*3;
  ex[0]=header1.bytes;
  ex[1]=header2.bytes;
  ex[2]=header3.bytes;
  memcpy(d,header1.packet,ex[0]);
  d+=ex[0];
  memcpy(d,header2.packet,ex[1]);
  d+=ex[1];
  memcpy(d,header3.packet,ex[2]);
  vorbis_comment_clear(&VC);
			
  printf("\n[Vorbis]Vorbis encoder initialized\n");
  switch(vorbisConf->mode)
  {
    case ADM_VORBIS_VBR:
      printf("[Vorbis]CBR Bitrate:%lu\n",config->bitrate);
      break;
    case ADM_VORBIS_QUALITY: //FIXME FIXME FIXME
      printf("[Vorbis]VBR Quality:%.1f\n",vorbisConf->quality);
    break;
    default:
      ADM_assert(0);
  }
   
  printf("[Vorbis]Channels  :%lu\n",_wavheader->channels);
  printf("[Vorbis]Frequency :%lu\n",_wavheader->frequency);
  return 1;
}
Exemple #2
0
/* The following function is basically a hacked version of the code in
 * examples/encoder_example.c */
void
write_vorbis_data_or_die (const char *filename, int srate, float q, const float * data, int count, int ch)
{
  FILE * file ;
  ogg_stream_state os;
  ogg_page         og;
  ogg_packet       op;
  vorbis_info      vi;
  vorbis_comment   vc;
  vorbis_dsp_state vd;
  vorbis_block     vb;

  int eos = 0, ret;

  if ((file = fopen (filename, "wb")) == NULL) {
    printf("\n\nError : fopen failed : %s\n", strerror (errno)) ;
    exit (1) ;
  }

  /********** Encode setup ************/

  vorbis_info_init (&vi);

  ret = vorbis_encode_init_vbr (&vi,ch,srate,q);
  if (ret) {
    printf ("vorbis_encode_init_vbr return %d\n", ret) ;
    exit (1) ;
  }

  vorbis_comment_init (&vc);
  vorbis_comment_add_tag (&vc,"ENCODER","test/util.c");
  vorbis_analysis_init (&vd,&vi);
  vorbis_block_init (&vd,&vb);

  ogg_stream_init (&os,12345678);

  {
    ogg_packet header;
    ogg_packet header_comm;
    ogg_packet header_code;

    vorbis_analysis_headerout (&vd,&vc,&header,&header_comm,&header_code);
    ogg_stream_packetin (&os,&header);
    ogg_stream_packetin (&os,&header_comm);
    ogg_stream_packetin (&os,&header_code);

    /* Ensures the audio data will start on a new page. */
    while (!eos){
        int result = ogg_stream_flush (&os,&og);
        if (result == 0)
            break;
        fwrite (og.header,1,og.header_len,file);
        fwrite (og.body,1,og.body_len,file);
    }

  }

  {
    /* expose the buffer to submit data */
    float **buffer = vorbis_analysis_buffer (&vd,count);
    int i;

    for(i=0;i<ch;i++)
      memcpy (buffer [i], data, count * sizeof (float)) ;

    /* tell the library how much we actually submitted */
    vorbis_analysis_wrote (&vd,count);
    vorbis_analysis_wrote (&vd,0);
  }

  while (vorbis_analysis_blockout (&vd,&vb) == 1) {
    vorbis_analysis (&vb,NULL);
    vorbis_bitrate_addblock (&vb);

    while (vorbis_bitrate_flushpacket (&vd,&op)) {
      ogg_stream_packetin (&os,&op);

      while (!eos) {
          int result = ogg_stream_pageout (&os,&og);
          if (result == 0)
              break;
          fwrite (og.header,1,og.header_len,file);
          fwrite (og.body,1,og.body_len,file);

          if (ogg_page_eos (&og))
              eos = 1;
      }
    }
  }

  ogg_stream_clear (&os);
  vorbis_block_clear (&vb);
  vorbis_dsp_clear (&vd);
  vorbis_comment_clear (&vc);
  vorbis_info_clear (&vi);

 fclose (file) ;
}
void rmdInitEncoder(ProgData *pdata,EncData *enc_data_t,int buffer_ready){
    
    int y0,
        y1,
        y2,
        fname_length;
    ogg_stream_state m_ogg_skel;
    ogg_page skel_og_pg;
    fisbone_packet skel_fbv,    //video fisbone packet
                   skel_fba ;   //audio fisbone packet

    (pdata)->enc_data=enc_data_t;

    fname_length=strlen(pdata->args.filename);
    if(!(fname_length>4 &&
       pdata->args.filename[fname_length-4] == '.' &&
       (pdata->args.filename[fname_length-3] == 'o' ||
        pdata->args.filename[fname_length-3] == 'O') &&
       (pdata->args.filename[fname_length-2] == 'g' ||
        pdata->args.filename[fname_length-2] == 'G') &&
       (pdata->args.filename[fname_length-1] == 'v' ||
        pdata->args.filename[fname_length-1] == 'V'))){
    
        char *new_name=malloc(fname_length+5);
        strcpy(new_name,pdata->args.filename);
        strcat(new_name,".ogv");
        
        free(pdata->args.filename);
        pdata->args.filename=new_name;


    }
        
    if (!pdata->args.overwrite) {
        rmdIncrementalNaming(&(pdata)->args.filename);
        fprintf(stderr, "Output file: %s\n", pdata->args.filename);
    }
        
    enc_data_t->fp=fopen((pdata)->args.filename,"w");
    if(enc_data_t->fp==NULL){
        fprintf(stderr,"Cannot open file %s for writting!\n",
                       (pdata)->args.filename);
        exit(13);
    }

    //each stream must have a unique 
    srand(time(NULL));
    y0=rand()+1;
    y1=rand()+1;
    y2=rand()+1;
    y2+=(y1==y2);
    y0=(((y0==y1)||(y0==y2))?(y1+y2):y0);

    //init ogg streams
    //skeleton first
    ogg_stream_init(&m_ogg_skel,y0);
    m_add_fishead_packet(&m_ogg_skel);
	if(ogg_stream_pageout(&m_ogg_skel,&skel_og_pg)!= 1){
        fprintf (stderr, "Internal Ogg library error.\n");
        exit (2);
    }
    fwrite(skel_og_pg.header,1,skel_og_pg.header_len,enc_data_t->fp);
    fwrite(skel_og_pg.body,1,skel_og_pg.body_len,enc_data_t->fp);
    


    ogg_stream_init(&enc_data_t->m_ogg_ts,y1);
    if(!pdata->args.nosound)
        ogg_stream_init(&enc_data_t->m_ogg_vs,y2);


    theora_info_init(&enc_data_t->m_th_inf);
    enc_data_t->m_th_inf.frame_width                  = pdata->brwin.rrect.width;
    enc_data_t->m_th_inf.frame_height                 = pdata->brwin.rrect.height;
    enc_data_t->m_th_inf.width                        = ((enc_data_t->m_th_inf.frame_width + 15) >> 4) << 4;
    enc_data_t->m_th_inf.height                       = ((enc_data_t->m_th_inf.frame_height + 15) >> 4) << 4;
    enc_data_t->m_th_inf.offset_x                     = 0;
    enc_data_t->m_th_inf.offset_y                     = 0;

    enc_data_t->m_th_inf.fps_numerator                = pdata->args.fps * 100.0;
    enc_data_t->m_th_inf.fps_denominator              = 100;
    enc_data_t->m_th_inf.aspect_numerator             = 1;
    enc_data_t->m_th_inf.aspect_denominator           = 1;

    enc_data_t->m_th_inf.colorspace                   = OC_CS_UNSPECIFIED;
    enc_data_t->m_th_inf.pixelformat                  = OC_PF_420;

    enc_data_t->m_th_inf.target_bitrate               = pdata->args.v_bitrate;
    enc_data_t->m_th_inf.quality                      = pdata->args.v_quality;
    enc_data_t->m_th_inf.dropframes_p                 = 0;
    enc_data_t->m_th_inf.quick_p                      = 1;
    enc_data_t->m_th_inf.keyframe_auto_p              = 1;
    enc_data_t->m_th_inf.keyframe_frequency           = 64;
    enc_data_t->m_th_inf.keyframe_frequency_force     = 64;
    enc_data_t->m_th_inf.keyframe_data_target_bitrate = enc_data_t->m_th_inf.quality * 1.5;
    enc_data_t->m_th_inf.keyframe_auto_threshold      = 80;
    enc_data_t->m_th_inf.keyframe_mindistance         = 8;
    enc_data_t->m_th_inf.noise_sensitivity            = 1;
    enc_data_t->m_th_inf.sharpness                    = 2;

    theora_encode_init(&enc_data_t->m_th_st,&enc_data_t->m_th_inf);


    if(!pdata->args.nosound){
        int ret;
        vorbis_info_init(&enc_data_t->m_vo_inf);
        ret = vorbis_encode_init_vbr(&enc_data_t->m_vo_inf,
                                     pdata->args.channels,
                                     pdata->args.frequency,
                                     (float)pdata->args.s_quality*0.1);
        if(ret){
            fprintf(stderr,"Error while setting up vorbis stream quality!\n");
            exit(2);
        }
        vorbis_comment_init(&enc_data_t->m_vo_cmmnt);
        vorbis_analysis_init(&enc_data_t->m_vo_dsp,&enc_data_t->m_vo_inf);
        vorbis_block_init(&enc_data_t->m_vo_dsp,&enc_data_t->m_vo_block);
    }


    theora_encode_header(&enc_data_t->m_th_st,&enc_data_t->m_ogg_pckt1);
    ogg_stream_packetin(&enc_data_t->m_ogg_ts,&enc_data_t->m_ogg_pckt1);
    if(ogg_stream_pageout(&enc_data_t->m_ogg_ts,&enc_data_t->m_ogg_pg)!=1){
        fprintf(stderr,"Internal Ogg library error.\n");
        exit(2);
    }
    fwrite(enc_data_t->m_ogg_pg.header,1,
           enc_data_t->m_ogg_pg.header_len,
           enc_data_t->fp);
    fwrite(enc_data_t->m_ogg_pg.body,1,
           enc_data_t->m_ogg_pg.body_len,
           enc_data_t->fp);

    theora_comment_init(&enc_data_t->m_th_cmmnt);
    theora_comment_add_tag(&enc_data_t->m_th_cmmnt,"recordMyDesktop",VERSION);
    theora_encode_comment(&enc_data_t->m_th_cmmnt,&enc_data_t->m_ogg_pckt1);
    ogg_stream_packetin(&enc_data_t->m_ogg_ts,&enc_data_t->m_ogg_pckt1);
    theora_encode_tables(&enc_data_t->m_th_st,&enc_data_t->m_ogg_pckt1);
    ogg_stream_packetin(&enc_data_t->m_ogg_ts,&enc_data_t->m_ogg_pckt1);


    if(!pdata->args.nosound){
        ogg_packet header;
        ogg_packet header_comm;
        ogg_packet header_code;

        vorbis_analysis_headerout(&enc_data_t->m_vo_dsp,
                                  &enc_data_t->m_vo_cmmnt,
                                  &header,&header_comm,
                                  &header_code);
        ogg_stream_packetin(&enc_data_t->m_ogg_vs,&header);
        if(ogg_stream_pageout(&enc_data_t->m_ogg_vs,&enc_data_t->m_ogg_pg)!=1){
            fprintf(stderr,"Internal Ogg library error.\n");
            exit(2);
        }
        fwrite(enc_data_t->m_ogg_pg.header,1,
               enc_data_t->m_ogg_pg.header_len,
               enc_data_t->fp);
        fwrite(enc_data_t->m_ogg_pg.body,1,
               enc_data_t->m_ogg_pg.body_len,
               enc_data_t->fp);

        ogg_stream_packetin(&enc_data_t->m_ogg_vs,&header_comm);
        ogg_stream_packetin(&enc_data_t->m_ogg_vs,&header_code);
    }

    //fishbone packets go here
    memset(&skel_fbv,0,sizeof(skel_fbv));
    skel_fbv.serial_no=enc_data_t->m_ogg_ts.serialno;
    skel_fbv.nr_header_packet=3;
    skel_fbv.granule_rate_n=enc_data_t->m_th_inf.fps_numerator;
    skel_fbv.granule_rate_d=enc_data_t->m_th_inf.fps_denominator;
    skel_fbv.start_granule=0;
    skel_fbv.preroll=0;
    skel_fbv.granule_shift=theora_granule_shift(&enc_data_t->m_th_inf);
    add_message_header_field(&skel_fbv,
                             "Content-Type",
                             "video/theora");

    add_fisbone_to_stream(&m_ogg_skel,&skel_fbv);

    if(!pdata->args.nosound){

        memset(&skel_fba,0,sizeof(skel_fba));
        skel_fba.serial_no=enc_data_t->m_ogg_vs.serialno;
        skel_fba.nr_header_packet=3;
        skel_fba.granule_rate_n=pdata->args.frequency;
        skel_fba.granule_rate_d=(ogg_int64_t)1;
        skel_fba.start_granule=0;
        skel_fba.preroll=2;
        skel_fba.granule_shift=0;
        add_message_header_field(&skel_fba,
                                 "Content-Type",
                                 "audio/vorbis");

        add_fisbone_to_stream(&m_ogg_skel,&skel_fba);
    
    }

    while(1){
        int result = ogg_stream_flush(&m_ogg_skel, &skel_og_pg);
        if(result<0){
            fprintf (stderr, "Internal Ogg library error.\n");
            exit(2);
        }
        if(result==0)
            break;
        fwrite(skel_og_pg.header,1,skel_og_pg.header_len,enc_data_t->fp);
        fwrite(skel_og_pg.body,1,skel_og_pg.body_len,enc_data_t->fp);
	}



    while(1){
        int result = ogg_stream_flush(&enc_data_t->m_ogg_ts,
                                      &enc_data_t->m_ogg_pg);
        if(result<0){
            fprintf(stderr,"Internal Ogg library error.\n");
            exit(2);
        }
        if(result==0)break;
        fwrite(enc_data_t->m_ogg_pg.header,1,
               enc_data_t->m_ogg_pg.header_len,
               enc_data_t->fp);
        fwrite(enc_data_t->m_ogg_pg.body,1,
               enc_data_t->m_ogg_pg.body_len,
               enc_data_t->fp);
    }

    if(!pdata->args.nosound){
        while(1){
            int result=ogg_stream_flush(&enc_data_t->m_ogg_vs,
                                        &enc_data_t->m_ogg_pg);
            if(result<0){
                fprintf(stderr,"Internal Ogg library error.\n");
                exit(2);
            }
            if(result==0)break;
            fwrite(enc_data_t->m_ogg_pg.header,1,
                   enc_data_t->m_ogg_pg.header_len,
                   enc_data_t->fp);
            fwrite(enc_data_t->m_ogg_pg.body,1,
                   enc_data_t->m_ogg_pg.body_len,
                   enc_data_t->fp);
        }
    }
    
    //skeleton eos
    add_eos_packet_to_stream(&m_ogg_skel);
	if(ogg_stream_flush(&m_ogg_skel,&skel_og_pg)<0){
        fprintf(stderr,"Internal Ogg library error.\n");
        exit(2);
    }
    fwrite(skel_og_pg.header,1,skel_og_pg.header_len,enc_data_t->fp);
    fwrite(skel_og_pg.body,1,skel_og_pg.body_len,enc_data_t->fp);


    //theora buffer allocation, if any
    if(!buffer_ready){
        enc_data_t->yuv.y=(unsigned char *)malloc(enc_data_t->m_th_inf.height*
                          enc_data_t->m_th_inf.width);
        enc_data_t->yuv.u=(unsigned char *)malloc(enc_data_t->m_th_inf.height*
                          enc_data_t->m_th_inf.width/4);
        enc_data_t->yuv.v=(unsigned char *)malloc(enc_data_t->m_th_inf.height*
                          enc_data_t->m_th_inf.width/4);
        enc_data_t->yuv.y_width=enc_data_t->m_th_inf.width;
        enc_data_t->yuv.y_height=enc_data_t->m_th_inf.height;
        enc_data_t->yuv.y_stride=enc_data_t->m_th_inf.width;

        enc_data_t->yuv.uv_width=enc_data_t->m_th_inf.width/2;
        enc_data_t->yuv.uv_height=enc_data_t->m_th_inf.height/2;
        enc_data_t->yuv.uv_stride=enc_data_t->m_th_inf.width/2;
        enc_data_t->x_offset=enc_data_t->m_th_inf.offset_x;
        enc_data_t->y_offset=enc_data_t->m_th_inf.offset_y;
    }
    theora_info_clear(&enc_data_t->m_th_inf);

}
Exemple #4
0
int ExportOGG::Export(AudacityProject *project,
                       int numChannels,
                       const wxString &fName,
                       bool selectionOnly,
                       double t0,
                       double t1,
                       MixerSpec *mixerSpec,
                       const Tags *metadata,
                       int WXUNUSED(subformat))
{
   double    rate    = project->GetRate();
   const TrackList *tracks = project->GetTracks();
   double    quality = (gPrefs->Read(wxT("/FileFormats/OggExportQuality"), 50)/(float)100.0);

   wxLogNull logNo;            // temporarily disable wxWidgets error messages
   int updateResult = eProgressSuccess;
   int       eos = 0;

   FileIO outFile(fName, FileIO::Output);

   if (!outFile.IsOpened()) {
      wxMessageBox(_("Unable to open target file for writing"));
      return false;
   }

   // All the Ogg and Vorbis encoding data
   ogg_stream_state stream;
   ogg_page         page;
   ogg_packet       packet;

   vorbis_info      info;
   vorbis_comment   comment;
   vorbis_dsp_state dsp;
   vorbis_block     block;

   // Encoding setup
   vorbis_info_init(&info);
   vorbis_encode_init_vbr(&info, numChannels, int(rate + 0.5), quality);

   // Retrieve tags
   if (!FillComment(project, &comment, metadata)) {
      return false;
   }

   // Set up analysis state and auxiliary encoding storage
   vorbis_analysis_init(&dsp, &info);
   vorbis_block_init(&dsp, &block);

   // Set up packet->stream encoder.  According to encoder example,
   // a random serial number makes it more likely that you can make
   // chained streams with concatenation.
   srand(time(NULL));
   ogg_stream_init(&stream, rand());

   // First we need to write the required headers:
   //    1. The Ogg bitstream header, which contains codec setup params
   //    2. The Vorbis comment header
   //    3. The bitstream codebook.
   //
   // After we create those our responsibility is complete, libvorbis will
   // take care of any other ogg bistream constraints (again, according
   // to the example encoder source)
   ogg_packet bitstream_header;
   ogg_packet comment_header;
   ogg_packet codebook_header;

   vorbis_analysis_headerout(&dsp, &comment, &bitstream_header, &comment_header,
         &codebook_header);

   // Place these headers into the stream
   ogg_stream_packetin(&stream, &bitstream_header);
   ogg_stream_packetin(&stream, &comment_header);
   ogg_stream_packetin(&stream, &codebook_header);

   // Flushing these headers now guarentees that audio data will
   // start on a NEW page, which apparently makes streaming easier
   while (ogg_stream_flush(&stream, &page)) {
      outFile.Write(page.header, page.header_len);
      outFile.Write(page.body, page.body_len);
   }

   const WaveTrackConstArray waveTracks =
      tracks->GetWaveTrackConstArray(selectionOnly, false);
   {
      auto mixer = CreateMixer(waveTracks,
         tracks->GetTimeTrack(),
         t0, t1,
         numChannels, SAMPLES_PER_RUN, false,
         rate, floatSample, true, mixerSpec);

      ProgressDialog progress(wxFileName(fName).GetName(),
         selectionOnly ?
         _("Exporting the selected audio as Ogg Vorbis") :
         _("Exporting the entire project as Ogg Vorbis"));

      while (updateResult == eProgressSuccess && !eos) {
         float **vorbis_buffer = vorbis_analysis_buffer(&dsp, SAMPLES_PER_RUN);
         sampleCount samplesThisRun = mixer->Process(SAMPLES_PER_RUN);

         if (samplesThisRun == 0) {
            // Tell the library that we wrote 0 bytes - signalling the end.
            vorbis_analysis_wrote(&dsp, 0);
         }
         else {

            for (int i = 0; i < numChannels; i++) {
               float *temp = (float *)mixer->GetBuffer(i);
               memcpy(vorbis_buffer[i], temp, sizeof(float)*SAMPLES_PER_RUN);
            }

            // tell the encoder how many samples we have
            vorbis_analysis_wrote(&dsp, samplesThisRun);
         }

         // I don't understand what this call does, so here is the comment
         // from the example, verbatim:
         //
         //    vorbis does some data preanalysis, then divvies up blocks
         //    for more involved (potentially parallel) processing. Get
         //    a single block for encoding now
         while (vorbis_analysis_blockout(&dsp, &block) == 1) {

            // analysis, assume we want to use bitrate management
            vorbis_analysis(&block, NULL);
            vorbis_bitrate_addblock(&block);

            while (vorbis_bitrate_flushpacket(&dsp, &packet)) {

               // add the packet to the bitstream
               ogg_stream_packetin(&stream, &packet);

               // From vorbis-tools-1.0/oggenc/encode.c:
               //   If we've gone over a page boundary, we can do actual output,
               //   so do so (for however many pages are available).

               while (!eos) {
                  int result = ogg_stream_pageout(&stream, &page);
                  if (!result) {
                     break;
                  }

                  outFile.Write(page.header, page.header_len);
                  outFile.Write(page.body, page.body_len);

                  if (ogg_page_eos(&page)) {
                     eos = 1;
                  }
               }
            }
         }

         updateResult = progress.Update(mixer->MixGetCurrentTime() - t0, t1 - t0);
      }
   }

   ogg_stream_clear(&stream);

   vorbis_block_clear(&block);
   vorbis_dsp_clear(&dsp);
   vorbis_info_clear(&info);
   vorbis_comment_clear(&comment);

   outFile.Close();

   return updateResult;
}
Exemple #5
0
int main(){
  ogg_stream_state os; /* take physical pages, weld into a logical
			  stream of packets */
  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 */

  int eos=0,ret;
  int i, founddata;

#if defined(macintosh) && defined(__MWERKS__)
  int argc = 0;
  char **argv = NULL;
  argc = ccommand(&argv); /* get a "command line" from the Mac user */
                          /* this also lets the user set stdin and stdout */
#endif

  /* we cheat on the WAV header; we just bypass 44 bytes and never
     verify that it matches 16bit/stereo/44.1kHz.  This is just an
     example, after all. */

#ifdef _WIN32 /* We need to set stdin/stdout to binary mode. Damn windows. */
  /* if we were reading/writing a file, it would also need to in
     binary mode, eg, fopen("file.wav","wb"); */
  /* Beware the evil ifdef. We avoid these where we can, but this one we 
     cannot. Don't add any more, you'll probably go to hell if you do. */
  _setmode( _fileno( stdin ), _O_BINARY );
  _setmode( _fileno( stdout ), _O_BINARY );
#endif


  /* we cheat on the WAV header; we just bypass the header and never
     verify that it matches 16bit/stereo/44.1kHz.  This is just an
     example, after all. */

  readbuffer[0] = '\0';
  for (i=0, founddata=0; i<30 && ! feof(stdin) && ! ferror(stdin); i++)
  {
    fread(readbuffer,1,2,stdin);

    if ( ! strncmp((char*)readbuffer, "da", 2) )
    {
      founddata = 1;
      fread(readbuffer,1,6,stdin);
      break;
    }
  }

  /********** Encode setup ************/

  vorbis_info_init(&vi);

  /* choose an encoding mode.  A few possibilities commented out, one
     actually used: */

  /*********************************************************************
   Encoding using a VBR quality mode.  The usable range is -.1
   (lowest quality, smallest file) to 1. (highest quality, largest file).
   Example quality mode .4: 44kHz stereo coupled, roughly 128kbps VBR 
  
   ret = vorbis_encode_init_vbr(&vi,2,44100,.4);

   ---------------------------------------------------------------------

   Encoding using an average bitrate mode (ABR).
   example: 44kHz stereo coupled, average 128kbps VBR 
  
   ret = vorbis_encode_init(&vi,2,44100,-1,128000,-1);

   ---------------------------------------------------------------------

   Encode using a quality mode, but select that quality mode by asking for
   an approximate bitrate.  This is not ABR, it is true VBR, but selected
   using the bitrate interface, and then turning bitrate management off:

   ret = ( vorbis_encode_setup_managed(&vi,2,44100,-1,128000,-1) ||
           vorbis_encode_ctl(&vi,OV_ECTL_RATEMANAGE2_SET,NULL) ||
           vorbis_encode_setup_init(&vi));

   *********************************************************************/

  ret=vorbis_encode_init_vbr(&vi,2,44100,0.1);

  /* do not continue if setup failed; this can happen if we ask for a
     mode that libVorbis does not support (eg, too low a bitrate, etc,
     will return 'OV_EIMPL') */

  if(ret)exit(1);

  /* add a comment */
  vorbis_comment_init(&vc);
  vorbis_comment_add_tag(&vc,"ENCODER","encoder_example.c");

  /* set up the analysis state and auxiliary encoding storage */
  vorbis_analysis_init(&vd,&vi);
  vorbis_block_init(&vd,&vb);
  
  /* set up our packet->stream encoder */
  /* pick a random serial number; that way we can more likely build
     chained streams just by concatenation */
  srand(time(NULL));
  ogg_stream_init(&os,rand());

  /* Vorbis streams begin with three headers; the initial header (with
     most of the codec setup parameters) which is mandated by the Ogg
     bitstream spec.  The second header holds any comment fields.  The
     third header holds the bitstream codebook.  We merely need to
     make the headers, then pass them to libvorbis one at a time;
     libvorbis handles the additional Ogg bitstream constraints */

  {
    ogg_packet header;
    ogg_packet header_comm;
    ogg_packet header_code;

    vorbis_analysis_headerout(&vd,&vc,&header,&header_comm,&header_code);
    ogg_stream_packetin(&os,&header); /* automatically placed in its own
					 page */
    ogg_stream_packetin(&os,&header_comm);
    ogg_stream_packetin(&os,&header_code);

	/* This ensures the actual
	 * audio data will start on a new page, as per spec
	 */
	while(!eos){
		int result=ogg_stream_flush(&os,&og);
		if(result==0)break;
		fwrite(og.header,1,og.header_len,stdout);
		fwrite(og.body,1,og.body_len,stdout);
	}

  }
  
  while(!eos){
    long i;
    long bytes=fread(readbuffer,1,READ*4,stdin); /* stereo hardwired here */

    if(bytes==0){
      /* end of file.  this can be done implicitly in the mainline,
         but it's easier to see here in non-clever fashion.
         Tell the library we're at end of stream so that it can handle
         the last frame and mark end of stream in the output properly */
      vorbis_analysis_wrote(&vd,0);

    }else{
      /* data to encode */

      /* expose the buffer to submit data */
      float **buffer=vorbis_analysis_buffer(&vd,READ);
      
      /* uninterleave samples */
      for(i=0;i<bytes/4;i++){
	buffer[0][i]=((readbuffer[i*4+1]<<8)|
		      (0x00ff&(int)readbuffer[i*4]))/32768.f;
	buffer[1][i]=((readbuffer[i*4+3]<<8)|
		      (0x00ff&(int)readbuffer[i*4+2]))/32768.f;
      }
    
      /* tell the library how much we actually submitted */
      vorbis_analysis_wrote(&vd,i);
    }

    /* vorbis does some data preanalysis, then divvies up blocks for
       more involved (potentially parallel) processing.  Get a single
       block for encoding now */
    while(vorbis_analysis_blockout(&vd,&vb)==1){

      /* analysis, assume we want to use bitrate management */
      vorbis_analysis(&vb,NULL);
      vorbis_bitrate_addblock(&vb);

      while(vorbis_bitrate_flushpacket(&vd,&op)){
	
	/* weld the packet into the bitstream */
	ogg_stream_packetin(&os,&op);
	
	/* write out pages (if any) */
	while(!eos){
	  int result=ogg_stream_pageout(&os,&og);
	  if(result==0)break;
	  fwrite(og.header,1,og.header_len,stdout);
	  fwrite(og.body,1,og.body_len,stdout);
	  
	  /* 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;
	}
      }
    }
  }

  /* clean up and exit.  vorbis_info_clear() must be called last */
  
  ogg_stream_clear(&os);
  vorbis_block_clear(&vb);
  vorbis_dsp_clear(&vd);
  vorbis_comment_clear(&vc);
  vorbis_info_clear(&vi);
  
  /* ogg_page and ogg_packet structs always point to storage in
     libvorbis.  They're never freed or manipulated directly */
  
  fprintf(stderr,"Done.\n");
  return(0);
}
Exemple #6
0
static SCM open_vorbis_stream(SCM server, SCM port, SCM password,
			SCM mount, SCM config) {
	SCM smob;
	double qual;
	char stream_name[32];
	VORBIS_STREAM *stream;
	stream = (VORBIS_STREAM *)my_gc_malloc(sizeof(VORBIS_STREAM),
				"vorbis_stream", "vorbis stream");
	stream->header.shutdown = vorbis_shutdown;
	vorbis_info_init(&(stream->vi));
	SCM quality = get_property(config, "quality");
	if (scm_is_number(quality)) qual = scm_to_double(quality);
	else qual = 0.6;
	scm_remember_upto_here_1(quality);
	stream->header.shoutbuf = NULL;
	stream->header.shoutbuf_size = 0;
	stream->header.rb_size = sizeof(sample_t) * RB_SECS * sampling_rate 
				* QMX_CHANNELS + 0.5;
	stream->header.ringbuf = jack_ringbuffer_create(stream->header.rb_size);
	if (vorbis_encode_init_vbr(&(stream->vi), QMX_CHANNELS,
				sampling_rate, qual) != 0) {
		log_msg("vorbis init failed\n");
		return SCM_BOOL_F;
		}
	if ((stream->header.shout = shout_new()) == NULL) {
		log_msg("can't create shout instance\n");
		return SCM_BOOL_F;
		}
	vorbis_analysis_init(&(stream->vd), &(stream->vi));
	vorbis_block_init(&(stream->vd), &(stream->vb));
	ogg_stream_init(&(stream->os), rand());
	vorbis_comment_init(&(stream->vc));
	vorbis_comment_add_tag(&(stream->vc), "ENCODER", "QMX");
	shout_set_protocol(stream->header.shout, SHOUT_PROTOCOL_HTTP);
	shout_set_format(stream->header.shout, SHOUT_FORMAT_OGG);
	char *server_s = scm_to_locale_string(server); // server
	shout_set_host(stream->header.shout, server_s);
	free(server_s);
	shout_set_port(stream->header.shout, scm_to_int(port)); // port
	shout_set_user(stream->header.shout, "source"); // user
	char *password_s = scm_to_locale_string(password); // password
	shout_set_password(stream->header.shout, password_s);
	free(password_s);
	char *mount_s = scm_to_locale_string(mount); // mount pt
	shout_set_mount(stream->header.shout, mount_s);
	SCM title = get_property(config, "title");
	if (scm_is_string(title)) {
		char *title_s = scm_to_locale_string(title);
		if (strlen(title_s) > 0)
			vorbis_comment_add_tag(&(stream->vc), "TITLE", title_s);
		free(title_s);
		}
	scm_remember_upto_here_1(title);
	SCM name = get_property(config, "name");
	stream_name[0] = '\0';
	if (scm_is_string(name)) {
		char *name_s = scm_to_locale_string(name);
		shout_set_name(stream->header.shout, name_s);
		snprintf(stream_name, sizeof(stream_name), "'%s' ", name_s);
		free(name_s);
		}
	scm_remember_upto_here_1(name);
	SCM description = get_property(config, "description");
	if (scm_is_string(description)) {
		char *description_s = scm_to_locale_string(description);
		shout_set_description(stream->header.shout, description_s);
		free(description_s);
		}
	scm_remember_upto_here_1(description);
	SCM genre = get_property(config, "genre");
	if (scm_is_string(genre)) {
		char *genre_s = scm_to_locale_string(genre);
		shout_set_genre(stream->header.shout, genre_s);
		free(genre_s);
		}
	scm_remember_upto_here_1(genre);
	shout_set_audio_info(stream->header.shout,
			SHOUT_AI_CHANNELS, encode_int(QMX_CHANNELS));
	shout_set_audio_info(stream->header.shout,
			SHOUT_AI_SAMPLERATE, encode_int(sampling_rate));
	if (shout_open(stream->header.shout) == SHOUTERR_SUCCESS) {
		log_msg("vorbis stream %smounted at %s\n", stream_name, mount_s);
		free(mount_s);
		}
	else {
		log_msg("vorbis stream %sfailed to open: %s\n", stream_name,
				shout_get_error(stream->header.shout));
		free(mount_s);
		shout_free(stream->header.shout);
		return SCM_BOOL_F;
		}
	vorbis_streams += 1;
	stream->header.eos = 0;
	SCM_NEWSMOB(smob, vorbis_stream_tag, stream);
	streams = link_in(streams, smob);
	stream->header.do_prep = need_prepper;
	need_prepper = 0;
	stream->header.bookmark = 0;
	add_outbuf_client(load_frames, process_frames, (void *)stream,
						"Ogg-Vorbis stream");
	spawn_detached_thread(shout_thread, (void *)&(stream->header));
	scm_remember_upto_here_1(smob);
	return smob;
	}
Exemple #7
0
bool ExportOGG(AudacityProject *project,
               bool stereo, wxString fName,
               bool selectionOnly, double t0, double t1)
{
   double    rate    = project->GetRate();
   wxWindow  *parent = project;
   TrackList *tracks = project->GetTracks();
   double    quality = (gPrefs->Read("/FileFormats/OggExportQuality", 50)/(float)100.0);

   wxLogNull logNo;            // temporarily disable wxWindows error messages 
   bool      cancelling = false;

   wxFFile outFile(fName, "wb");

   if(!outFile.IsOpened()) {
      wxMessageBox(_("Unable to open target file for writing"));
      return false;
   }

   // All the Ogg and Vorbis encoding data
   ogg_stream_state stream;
   ogg_page         page;
   ogg_packet       packet;

   vorbis_info      info;
   vorbis_comment   comment;
   vorbis_dsp_state dsp;
   vorbis_block     block;

   // Encoding setup
   vorbis_info_init(&info);
   vorbis_encode_init_vbr(&info, stereo ? 2 : 1, int(rate + 0.5), quality);

   vorbis_comment_init(&comment);
   // If we wanted to add comments, we would do it here

   // Set up analysis state and auxiliary encoding storage
   vorbis_analysis_init(&dsp, &info);
   vorbis_block_init(&dsp, &block);

   // Set up packet->stream encoder.  According to encoder example,
   // a random serial number makes it more likely that you can make
   // chained streams with concatenation.
   srand(time(NULL));
   ogg_stream_init(&stream, rand());

   // First we need to write the required headers:
   //    1. The Ogg bitstream header, which contains codec setup params
   //    2. The Vorbis comment header
   //    3. The bitstream codebook.
   //
   // After we create those our responsibility is complete, libvorbis will
   // take care of any other ogg bistream constraints (again, according
   // to the example encoder source)
   ogg_packet bitstream_header;
   ogg_packet comment_header;
   ogg_packet codebook_header;

   vorbis_analysis_headerout(&dsp, &comment, &bitstream_header, &comment_header,
         &codebook_header);

   // Place these headers into the stream
   ogg_stream_packetin(&stream, &bitstream_header);
   ogg_stream_packetin(&stream, &comment_header);
   ogg_stream_packetin(&stream, &codebook_header);

   // Flushing these headers now guarentees that audio data will
   // start on a new page, which apparently makes streaming easier
   ogg_stream_flush(&stream, &page);
   outFile.Write(page.header, page.header_len);
   outFile.Write(page.body, page.body_len);

   double t = t0;
   bool   done = false;
   wxProgressDialog *progress = NULL;

   wxYield();
   wxStartTimer();

   while(!done && !cancelling){
      float       deltat = (float)SAMPLES_PER_RUN / rate;
      sampleCount samplesThisRun = SAMPLES_PER_RUN;
      Mixer       *mixer = new Mixer(stereo ? 2 : 1, SAMPLES_PER_RUN, 
            /* interleaved = */ false, rate, floatSample);

      if(t + deltat > t1) {
         done = true;
         deltat = t1 - t;
         samplesThisRun = int(deltat * rate + 0.5);
      }
      
      mixer->Clear();

      TrackListIterator iter(tracks);
      Track *tr = iter.First();
      while (tr) {
         if (tr->GetKind() == Track::Wave) {
            if (tr->GetSelected() || !selectionOnly) {
               if (tr->GetChannel() == Track::MonoChannel)
                  mixer->MixMono((WaveTrack *) tr, t, t + deltat);
               else if (tr->GetChannel() == Track::LeftChannel)
                  mixer->MixLeft((WaveTrack *) tr, t, t + deltat);
               else if (tr->GetChannel() == Track::RightChannel)
                  mixer->MixRight((WaveTrack *) tr, t, t + deltat);
            }
         }
         tr = iter.Next();
      }
      
      float **vorbis_buffer = vorbis_analysis_buffer(&dsp, SAMPLES_PER_RUN);
      
      float *left = (float *)mixer->GetBuffer(0);
      memcpy(vorbis_buffer[0], left, sizeof(float)*SAMPLES_PER_RUN);

      if(stereo) {
         float *right = (float *)mixer->GetBuffer(1);
         memcpy(vorbis_buffer[1], right, sizeof(float)*SAMPLES_PER_RUN);
      }

      // tell the encoder how many samples we have
      vorbis_analysis_wrote(&dsp, samplesThisRun);

      // I don't understand what this call does, so here is the comment
      // from the example, verbatim:
      //
      //    vorbis does some data preanalysis, then divvies up blocks
      //    for more involved (potentially parallel) processing. Get
      //    a single block for encoding now
      while(vorbis_analysis_blockout(&dsp, &block) == 1) {

         // analysis, assume we want to use bitrate management
         vorbis_analysis(&block, NULL);
         vorbis_bitrate_addblock(&block);

         while(vorbis_bitrate_flushpacket(&dsp, &packet)) {

            // add the packet to the bitstream
            ogg_stream_packetin(&stream, &packet);
            int result = ogg_stream_pageout(&stream, &page);

            if(result != 0) {
               outFile.Write(page.header, page.header_len);
               outFile.Write(page.body, page.body_len);
            }
         }
      }

      if(progress)
         cancelling = !progress->Update(int (((t - t0) * 1000) / (t1 - t0) + 0.5));
      else if(wxGetElapsedTime(false) > 500) {
            
         wxString message = selectionOnly ?
            _("Exporting the selected audio as Ogg Vorbis") :
            _("Exporting the entire project as Ogg Vorbis");

         progress = new wxProgressDialog(
               _("Export"),
               message,
               1000,
               parent,
               wxPD_CAN_ABORT | wxPD_REMAINING_TIME | wxPD_AUTO_HIDE);
      }

      delete mixer;
      t += deltat;
   }

   outFile.Close();

   if(progress)
      delete progress;

   return true;
}
/*------------------------------------------------------------------------------
 *  Open an encoding session
 *----------------------------------------------------------------------------*/
bool
VorbisLibEncoder :: open ( void )
                                                            throw ( Exception )
{
    int     ret;

    if ( isOpen() ) {
        close();
    }

    vorbis_info_init( &vorbisInfo);

    switch ( getOutBitrateMode() ) {

        case cbr:
            ret = vorbis_encode_setup_managed( &vorbisInfo,
                                               getInChannel(),
                                               getOutSampleRate(),
                                               -1,
                                               getOutBitrate() * 1000,
                                               -1)
               || vorbis_encode_ctl( &vorbisInfo, OV_ECTL_RATEMANAGE_AVG, NULL)
               || vorbis_encode_setup_init( &vorbisInfo);
            if ( ret ) {
                throw Exception( __FILE__, __LINE__,
                                 "vorbis encode init error", ret);
            }
            break;

        case abr:
            if ( (ret = vorbis_encode_init( &vorbisInfo,
                                            getInChannel(),
                                            getOutSampleRate(),
                                            -1,
                                            getOutBitrate() * 1000,
                                            -1 )) ) {
                throw Exception( __FILE__, __LINE__,
                                 "vorbis encode init error", ret);
            }
            break;

        case vbr:
            if ( (ret = vorbis_encode_init_vbr( &vorbisInfo,
                                                getInChannel(),
                                                getOutSampleRate(),
                                                getOutQuality() )) ) {
                throw Exception( __FILE__, __LINE__,
                                 "vorbis encode init error", ret);
            }
            break;
    }

    if ( (ret = vorbis_analysis_init( &vorbisDspState, &vorbisInfo)) ) {
        throw Exception( __FILE__, __LINE__, "vorbis analysis init error", ret);
    }

    if ( (ret = vorbis_block_init( &vorbisDspState, &vorbisBlock)) ) {
        throw Exception( __FILE__, __LINE__, "vorbis block init error", ret);
    }

    if ( (ret = ogg_stream_init( &oggStreamState, 0)) ) {
        throw Exception( __FILE__, __LINE__, "ogg stream init error", ret);
    }

    // open the underlying sink
    if ( !sink->open() ) {
        throw Exception( __FILE__, __LINE__,
                         "vorbis lib opening underlying sink error");
    }

    // create an empty vorbis_comment structure
    vorbis_comment_init( &vorbisComment);

    // create the vorbis stream headers and send them to the underlying sink
    ogg_packet      header;
    ogg_packet      commentHeader;
    ogg_packet      codeHeader;

    if ( (ret = vorbis_analysis_headerout( &vorbisDspState,
                                           &vorbisComment,
                                           &header,
                                           &commentHeader,
                                           &codeHeader )) ) {
        throw Exception( __FILE__, __LINE__, "vorbis header init error", ret);
    }

    ogg_stream_packetin( &oggStreamState, &header);
    ogg_stream_packetin( &oggStreamState, &commentHeader);
    ogg_stream_packetin( &oggStreamState, &codeHeader);

    ogg_page        oggPage;
    while ( ogg_stream_flush( &oggStreamState, &oggPage) ) {
        sink->write( oggPage.header, oggPage.header_len);
        sink->write( oggPage.body, oggPage.body_len);
    }

    vorbis_comment_clear( &vorbisComment );

    // initialize the resampling coverter if needed
    if ( converter ) {
        converter->initialize( resampleRatio, getInChannel());
    }

    encoderOpen = true;

    return true;
}
S32 encode_vorbis_file(const std::string& in_fname, const std::string& out_fname)
{
#define READ_BUFFER 1024
	unsigned char readbuffer[READ_BUFFER*4+44];   /* out of the data segment, not the stack */	/*Flawfinder: ignore*/

	ogg_stream_state os; /* take physical pages, weld into a logical stream of packets */
	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 */
	
	int eos=0;
	int result;

	U16 num_channels = 0;
	U32 sample_rate = 0;
	U32 bits_per_sample = 0;

	S32 format_error = 0;
	std::string error_msg;
	if ((format_error = check_for_invalid_wav_formats(in_fname, error_msg)))
	{
		llwarns << error_msg << ": " << in_fname << llendl;
		return(format_error);
	}

#if 1
	unsigned char wav_header[44];	/*Flawfinder: ignore*/

	S32 data_left = 0;

	LLAPRFile infile ;
	infile.open(in_fname,LL_APR_RB, LLAPRFile::global);
	if (!infile.getFileHandle())
	{
		llwarns << "Couldn't open temporary ogg file for writing: " << in_fname
			<< llendl;
		return(LLVORBISENC_SOURCE_OPEN_ERR);
	}

	LLAPRFile outfile ;
	outfile.open(out_fname,LL_APR_WPB, LLAPRFile::global);
	if (!outfile.getFileHandle())
	{
		llwarns << "Couldn't open upload sound file for reading: " << in_fname
			<< llendl;
		return(LLVORBISENC_DEST_OPEN_ERR);
	}
	
	 // parse the chunks
	 U32 chunk_length = 0;
	 U32 file_pos = 12;  // start at the first chunk (usually fmt but not always)
	 
	 while (infile.eof() != APR_EOF)
	 {
		 infile.seek(APR_SET,file_pos);
		 infile.read(wav_header, 44);
		 
		 chunk_length = ((U32) wav_header[7] << 24) 
			 + ((U32) wav_header[6] << 16) 
			 + ((U32) wav_header[5] << 8) 
			 + wav_header[4];
		 
//		 llinfos << "chunk found: '" << wav_header[0] << wav_header[1] << wav_header[2] << wav_header[3] << "'" << llendl;
		 
		 if (!(strncmp((char *)&(wav_header[0]),"fmt ",4)))
		 {
			 num_channels = ((U16) wav_header[11] << 8) + wav_header[10];
			 sample_rate = ((U32) wav_header[15] << 24) 
				 + ((U32) wav_header[14] << 16) 
				 + ((U32) wav_header[13] << 8) 
				 + wav_header[12];
			 bits_per_sample = ((U16) wav_header[23] << 8) + wav_header[22];
		 }
	 	 else if (!(strncmp((char *)&(wav_header[0]),"data",4)))
		 {
			 infile.seek(APR_SET,file_pos+8);
			 // leave the file pointer at the beginning of the data chunk data
			 data_left = chunk_length;			
			 break;
		 }
		 file_pos += (chunk_length + 8);
		 chunk_length = 0;
	 } 
	 

	 /********** Encode setup ************/
	 
	 /* choose an encoding mode */
	 /* (mode 0: 44kHz stereo uncoupled, roughly 128kbps VBR) */
	 vorbis_info_init(&vi);

	 // always encode to mono

	 // SL-52913 & SL-53779 determined this quality level to be our 'good
	 // enough' general-purpose quality level with a nice low bitrate.
	 // Equivalent to oggenc -q0.5
	 F32 quality = 0.05f;
//	 quality = (bitrate==128000 ? 0.4f : 0.1);

//	 if (vorbis_encode_init(&vi, /* num_channels */ 1 ,sample_rate, -1, bitrate, -1))
	 if (vorbis_encode_init_vbr(&vi, /* num_channels */ 1 ,sample_rate, quality))
//	 if (vorbis_encode_setup_managed(&vi,1,sample_rate,-1,bitrate,-1) ||
//		vorbis_encode_ctl(&vi,OV_ECTL_RATEMANAGE_AVG,NULL) ||
//		vorbis_encode_setup_init(&vi))
	{
		llwarns << "unable to initialize vorbis codec at quality " << quality << llendl;
		//		llwarns << "unable to initialize vorbis codec at bitrate " << bitrate << llendl;
		return(LLVORBISENC_DEST_OPEN_ERR);
	}
	 
	 /* add a comment */
	 vorbis_comment_init(&vc);
//	 vorbis_comment_add(&vc,"Linden");
	 
	 /* set up the analysis state and auxiliary encoding storage */
	 vorbis_analysis_init(&vd,&vi);
	 vorbis_block_init(&vd,&vb);
	 
	 /* set up our packet->stream encoder */
	 /* pick a random serial number; that way we can more likely build
		chained streams just by concatenation */
	 ogg_stream_init(&os, ll_rand());
	 
	 /* Vorbis streams begin with three headers; the initial header (with
		most of the codec setup parameters) which is mandated by the Ogg
		bitstream spec.  The second header holds any comment fields.  The
		third header holds the bitstream codebook.  We merely need to
		make the headers, then pass them to libvorbis one at a time;
		libvorbis handles the additional Ogg bitstream constraints */
	 
	 {
		 ogg_packet header;
		 ogg_packet header_comm;
		 ogg_packet header_code;
		 
		 vorbis_analysis_headerout(&vd,&vc,&header,&header_comm,&header_code);
		 ogg_stream_packetin(&os,&header); /* automatically placed in its own
											  page */
		 ogg_stream_packetin(&os,&header_comm);
		 ogg_stream_packetin(&os,&header_code);
		 
		 /* We don't have to write out here, but doing so makes streaming 
		  * much easier, so we do, flushing ALL pages. This ensures the actual
		  * audio data will start on a new page
		  */
		 while(!eos){
			 int result=ogg_stream_flush(&os,&og);
			 if(result==0)break;
			 outfile.write(og.header, og.header_len);
			 outfile.write(og.body, og.body_len);
		 }
		 
	 }
	 
	 
	 while(!eos)
	 {
		 long bytes_per_sample = bits_per_sample/8;

		 long bytes=(long)infile.read(readbuffer,llclamp((S32)(READ_BUFFER*num_channels*bytes_per_sample),0,data_left)); /* stereo hardwired here */
		 
		 if (bytes==0)
		 {
			 /* end of file.  this can be done implicitly in the mainline,
				but it's easier to see here in non-clever fashion.
				Tell the library we're at end of stream so that it can handle
				the last frame and mark end of stream in the output properly */

			 vorbis_analysis_wrote(&vd,0);
//			 eos = 1;
			 
		 }
		 else
		 {
			 long i;
			 long samples;
			 int temp;

			 data_left -= bytes;
             /* data to encode */
			 
			 /* expose the buffer to submit data */
			 float **buffer=vorbis_analysis_buffer(&vd,READ_BUFFER);
			
			 i = 0;
			 samples = bytes / (num_channels * bytes_per_sample);

			 if (num_channels == 2)
			 {
				 if (bytes_per_sample == 2)
				 {
					 /* uninterleave samples */
					 for(i=0; i<samples ;i++)
					 {
					 	 temp =  ((signed char *)readbuffer)[i*4+1];	/*Flawfinder: ignore*/
						 temp += ((signed char *)readbuffer)[i*4+3];	/*Flawfinder: ignore*/
						 temp <<= 8;
						 temp += readbuffer[i*4];
						 temp += readbuffer[i*4+2];

						 buffer[0][i] = ((float)temp) / 65536.f;
					 }
				 }
				 else // presume it's 1 byte per which is unsigned (F#@%ing wav "standard")
				 {
					 /* uninterleave samples */
					 for(i=0; i<samples ;i++)
					 {
					 	 temp  = readbuffer[i*2+0];
						 temp += readbuffer[i*2+1];
						 temp -= 256;
						 buffer[0][i] = ((float)temp) / 256.f;
					 }
				 } 
			 }
			 else if (num_channels == 1)
			 {
				 if (bytes_per_sample == 2)
				 {
					 for(i=0; i < samples ;i++)
					 {
					 	 temp = ((signed char*)readbuffer)[i*2+1];
						 temp <<= 8;
						 temp += readbuffer[i*2];
						 buffer[0][i] = ((float)temp) / 32768.f;
					 }
				 }
				 else // presume it's 1 byte per which is unsigned (F#@%ing wav "standard")
				 {
					 for(i=0; i < samples ;i++)
					 {
						 temp = readbuffer[i];
						 temp -= 128;
						 buffer[0][i] = ((float)temp) / 128.f;
					 }
				 }
			 }
				
			 /* tell the library how much we actually submitted */
			 vorbis_analysis_wrote(&vd,i);
		 }
			 
		 /* vorbis does some data preanalysis, then divvies up blocks for
			more involved (potentially parallel) processing.  Get a single
			block for encoding now */
		 while(vorbis_analysis_blockout(&vd,&vb)==1)
		 {
			 
			 /* analysis */
			/* Do the main analysis, creating a packet */
			vorbis_analysis(&vb, NULL);
			vorbis_bitrate_addblock(&vb);

			while(vorbis_bitrate_flushpacket(&vd, &op)) 
			{
			 
			 /* weld the packet into the bitstream */
			 ogg_stream_packetin(&os,&op);
			 
			 /* write out pages (if any) */
			 while(!eos)
			 {
				 result = ogg_stream_pageout(&os,&og);

				 if(result==0)
				 	break;

				 outfile.write(og.header, og.header_len);
				 outfile.write(og.body, og.body_len);
				 
				 /* 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;
				 
			 }
			}
		 }
	 }
	 
	 
	 
	 /* clean up and exit.  vorbis_info_clear() must be called last */
	 
	 ogg_stream_clear(&os);
	 vorbis_block_clear(&vb);
	 vorbis_dsp_clear(&vd);
	 vorbis_comment_clear(&vc);
	 vorbis_info_clear(&vi);
	 
	 /* ogg_page and ogg_packet structs always point to storage in
		libvorbis.  They're never freed or manipulated directly */
	 
//	 fprintf(stderr,"Vorbis encoding: Done.\n");
	 llinfos << "Vorbis encoding: Done." << llendl;
	 
#endif
	 return(LLVORBISENC_NOERR);
	 
}
//Method to start encoding
int startEncoding(JNIEnv *env, jclass *cls_ptr, jlong *sampleRate_ptr, jlong *channels_ptr, jfloat *quality_ptr, jlong *bitrate_ptr, jobject *encoderDataFeed_ptr, int type) {
    //Dereference our variables
    jclass cls = (*cls_ptr);
    jlong sampleRate = (*sampleRate_ptr);
    jlong channels = (*channels_ptr);
    jfloat quality = (*quality_ptr);
    jlong bitrate = (*bitrate_ptr);
    jobject encoderDataFeed = (*encoderDataFeed_ptr);

    //Create our PCM data buffer
    signed char readbuffer[READ*4+44];

    //Create a new java byte array to pass to the data feed method
    jbyteArray jByteArrayBuffer = (*env)->NewByteArray(env, READ*4);

    //Create a new java byte buffer to write to
    jbyteArray jByteArrayWriteBuffer = (*env)->NewByteArray(env, READ*8);

    //Find our java classes we'll be calling
    jclass encoderDataFeedClass = (*env)->FindClass(env, "org/xiph/vorbis/encoder/EncodeFeed");

    //Find our java method id's we'll be calling
    jmethodID writeVorbisDataMethodId = (*env)->GetMethodID(env, encoderDataFeedClass, "writeVorbisData", "([BI)I");
    jmethodID readPCMDataMethodId = (*env)->GetMethodID(env, encoderDataFeedClass, "readPCMData", "([BI)J");
    jmethodID startMethodId = (*env)->GetMethodID(env, encoderDataFeedClass, "start", "()V");
    jmethodID stopMethodId = (*env)->GetMethodID(env, encoderDataFeedClass, "stop", "()V");

    ogg_stream_state os; /* take physical pages, weld into a logical
                            stream of packets */
    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 */

    int eos=0,ret;
    int i, founddata;

    /********** Encode setup ************/
    __android_log_print(ANDROID_LOG_INFO, "VorbisEncoder", "Setting up encoding");
    vorbis_info_init(&vi);

    /* choose an encoding mode.  A few possibilities commented out, one
       actually used: */

    /*********************************************************************
     Encoding using a VBR quality mode.  The usable range is -.1
     (lowest quality, smallest file) to 1. (highest quality, largest file).
     Example quality mode .4: 44kHz stereo coupled, roughly 128kbps VBR

     ret = vorbis_encode_init_vbr(&vi,2,44100,.4);

     ---------------------------------------------------------------------

     Encoding using an average bitrate mode (ABR).
     example: 44kHz stereo coupled, average 128kbps VBR

     ret = vorbis_encode_init(&vi,2,44100,-1,128000,-1);

     ---------------------------------------------------------------------

     Encode using a quality mode, but select that quality mode by asking for
     an approximate bitrate.  This is not ABR, it is true VBR, but selected
     using the bitrate interface, and then turning bitrate management off:

     ret = ( vorbis_encode_setup_managed(&vi,2,44100,-1,128000,-1) ||
             vorbis_encode_ctl(&vi,OV_ECTL_RATEMANAGE2_SET,NULL) ||
             vorbis_encode_setup_init(&vi));

     *********************************************************************/
     switch(type) {
        case WITH_BITRATE:
            __android_log_print(ANDROID_LOG_INFO, "VorbisEncoder", "Initializing with %lld channels %lldHz sample rate and %lld bitrate", channels, sampleRate, bitrate);
            ret=vorbis_encode_init(&vi, (long)channels, (long)sampleRate, (long)-1, (long)bitrate, (long)-1);
            break;
        case WITH_QUALITY:
            __android_log_print(ANDROID_LOG_INFO, "VorbisEncoder", "Initializing with %lld channels %lldHz sample rate and %f quality", channels, sampleRate, quality);
            ret=vorbis_encode_init_vbr(&vi, (long)channels, (long)sampleRate, (float)quality);
            break;
        default:
            __android_log_print(ANDROID_LOG_ERROR, "VorbisEncoder", "Failed to initialize");
            stopEncodeFeed(env, &encoderDataFeed, &stopMethodId);
            return ERROR_INITIALIZING;
     }


    /* do not continue if setup failed; this can happen if we ask for a
       mode that libVorbis does not support (eg, too low a bitrate, etc,
       will return 'OV_EIMPL') */

    if(ret) {
      __android_log_print(ANDROID_LOG_ERROR, "VorbisEncoder", "Failed to initialize");
      stopEncodeFeed(env, &encoderDataFeed, &stopMethodId);
      return ERROR_INITIALIZING;
    }

    startEncodeFeed(env, &encoderDataFeed, &startMethodId);

    /* add a comment */
    __android_log_print(ANDROID_LOG_DEBUG, "VorbisEncoder", "Adding comments");
    vorbis_comment_init(&vc);
    vorbis_comment_add_tag(&vc,"ENCODER","JNIVorbisEncoder");

    /* set up the analysis state and auxiliary encoding storage */
    vorbis_analysis_init(&vd,&vi);
    vorbis_block_init(&vd,&vb);

    /* set up our packet->stream encoder */
    /* pick a random serial number; that way we can more likely build
       chained streams just by concatenation */
    srand(time(NULL));
    ogg_stream_init(&os,rand());

    /* Vorbis streams begin with three headers; the initial header (with
       most of the codec setup parameters) which is mandated by the Ogg
       bitstream spec.  The second header holds any comment fields.  The
       third header holds the bitstream codebook.  We merely need to
       make the headers, then pass them to libvorbis one at a time;
       libvorbis handles the additional Ogg bitstream constraints */

    {
      ogg_packet header;
      ogg_packet header_comm;
      ogg_packet header_code;

      vorbis_analysis_headerout(&vd,&vc,&header,&header_comm,&header_code);
      ogg_stream_packetin(&os,&header); /* automatically placed in its own
                                           page */
      ogg_stream_packetin(&os,&header_comm);
      ogg_stream_packetin(&os,&header_code);

      /* This ensures the actual
       * audio data will start on a new page, as per spec
       */
      __android_log_print(ANDROID_LOG_INFO, "VorbisEncoder", "Writting header");
      while(!eos){
        int result=ogg_stream_flush(&os,&og);
        if(result==0)break;
        writeVorbisDataToEncoderDataFeed(env, &encoderDataFeed, &writeVorbisDataMethodId, og.header, og.header_len, &jByteArrayWriteBuffer);
        writeVorbisDataToEncoderDataFeed(env, &encoderDataFeed, &writeVorbisDataMethodId, og.body, og.body_len, &jByteArrayWriteBuffer);
      }

    }

    __android_log_print(ANDROID_LOG_INFO, "VorbisEncoder", "Starting to read from pcm callback");
    while(!eos){
      long i;
      long bytes = readPCMDataFromEncoderDataFeed(env, &encoderDataFeed, &readPCMDataMethodId, readbuffer, READ*4, &jByteArrayBuffer);

      if(bytes==0){
        /* end of file.  this can be done implicitly in the mainline,
           but it's easier to see here in non-clever fashion.
           Tell the library we're at end of stream so that it can handle
           the last frame and mark end of stream in the output properly */
        __android_log_print(ANDROID_LOG_INFO, "VorbisEncoder", "End of file");
        vorbis_analysis_wrote(&vd,0);

      }else{
        /* data to encode */

        /* expose the buffer to submit data */
        float **buffer=vorbis_analysis_buffer(&vd,bytes/(2*channels));

        /* uninterleave samples */
        int channel;
        for(i=0;i<bytes/(2*channels);i++) {
            for(channel = 0; channel < channels; channel++) {
                buffer[channel][i]=((readbuffer[i*(2*channels)+(channel*2+1)]<<8)|
                              (0x00ff&(int)readbuffer[i*(2*channels)+(channel*2)]))/32768.f;
            }
        }

        /* tell the library how much we actually submitted */
        vorbis_analysis_wrote(&vd,i);
      }

      /* vorbis does some data preanalysis, then divvies up blocks for
         more involved (potentially parallel) processing.  Get a single
         block for encoding now */
      while(vorbis_analysis_blockout(&vd,&vb)==1){

        /* analysis, assume we want to use bitrate management */
        vorbis_analysis(&vb,NULL);
        vorbis_bitrate_addblock(&vb);

        while(vorbis_bitrate_flushpacket(&vd,&op)){

          /* weld the packet into the bitstream */
          ogg_stream_packetin(&os,&op);

          /* write out pages (if any) */
          while(!eos){
            int result=ogg_stream_pageout(&os,&og);
            if(result==0)break;
            writeVorbisDataToEncoderDataFeed(env, &encoderDataFeed, &writeVorbisDataMethodId, og.header, og.header_len, &jByteArrayWriteBuffer);
            writeVorbisDataToEncoderDataFeed(env, &encoderDataFeed, &writeVorbisDataMethodId, og.body, og.body_len, &jByteArrayWriteBuffer);

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

    /* clean up and exit.  vorbis_info_clear() must be called last */
    __android_log_print(ANDROID_LOG_INFO, "VorbisEncoder", "Cleaning up encoder");
    ogg_stream_clear(&os);
    vorbis_block_clear(&vb);
    vorbis_dsp_clear(&vd);
    vorbis_comment_clear(&vc);
    vorbis_info_clear(&vi);

    /* ogg_page and ogg_packet structs always point to storage in
       libvorbis.  They're never freed or manipulated directly */
    __android_log_print(ANDROID_LOG_INFO, "VorbisEncoder", "Completed encoding.");
    stopEncodeFeed(env, &encoderDataFeed, &stopMethodId);

    //Clean up encode buffers
    (*env)->DeleteLocalRef(env, jByteArrayBuffer);
    (*env)->DeleteLocalRef(env, jByteArrayWriteBuffer);

    return SUCCESS;
}
Exemple #11
0
static LONG APIENTRY IOProc_Entry2(PVOID pmmioStr, USHORT usMsg, LONG lParam1,
                     LONG lParam2) {
	PMMIOINFO pmmioinfo = (PMMIOINFO)pmmioStr;
	switch (usMsg) {
	case MMIOM_OPEN:
		{	
     		HMMIO hmmioSS;
     		MMIOINFO mmioinfoSS;
	    	PSZ pszFileName = (char *)lParam1;
   	 		if (!pmmioinfo) return MMIO_ERROR;
  	  		if ((pmmioinfo->ulFlags & MMIO_READWRITE)) {
#ifdef DEBUG
			fprintf(file,"ReadWrite - requested.\n");
#endif
   	  		   return MMIO_ERROR;
  	  		}
			if (!(pmmioinfo->ulTranslate & MMIO_TRANSLATEHEADER) &&
			    !(pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA)) return MMIO_ERROR;
			if (!pmmioinfo->fccChildIOProc) {
				FOURCC fccFileStorageSystem;
				if (pmmioinfo->ulFlags & MMIO_CREATE) {
       				if (mmioDetermineSSIOProc(pszFileName, pmmioinfo, &fccFileStorageSystem, NULL)) {
              			fccFileStorageSystem = FOURCC_DOS;
              		}
       			} else {
	        		if (mmioIdentifyStorageSystem(pszFileName, pmmioinfo, &fccFileStorageSystem)) {
 		           		return MMIO_ERROR;
    	        	}
    	        }
            	if (!fccFileStorageSystem) {
             	  	return MMIO_ERROR;
            	} else {
             	  	pmmioinfo->fccChildIOProc = fccFileStorageSystem;
            	} /* endif */
			}
			memmove(&mmioinfoSS, pmmioinfo, sizeof(MMIOINFO));
			mmioinfoSS.pIOProc = NULL;
			mmioinfoSS.fccIOProc = pmmioinfo->fccChildIOProc;
			mmioinfoSS.ulFlags |= MMIO_NOIDENTIFY;
			
			hmmioSS = mmioOpen (pszFileName, &mmioinfoSS, mmioinfoSS.ulFlags);
			if (pmmioinfo->ulFlags & MMIO_DELETE) {
      			if (!hmmioSS) {
            		pmmioinfo->ulErrorRet = MMIOERR_DELETE_FAILED;
            		return MMIO_ERROR;
            	}
            	else return MMIO_SUCCESS;
			}
   			if (!hmmioSS) return MMIO_ERROR;
   			if (pmmioinfo->ulFlags & MMIO_READ) {
 			   DecInfo *decInfo = (DecInfo *)malloc(sizeof(DecInfo));
#ifdef DEBUG
			fprintf(file,"File Read: %s\n",pszFileName);
#endif
        		if (!decInfo) {
  	          		mmioClose(hmmioSS, 0);
            		return MMIO_ERROR;
	            }
				decInfo->t = READNUM;
			    decInfo->vorbisOptions = pmmioinfo->pExtraInfoStruct;
 	      		pmmioinfo->pExtraInfoStruct = (PVOID)decInfo;
  	     		{
            		ov_callbacks cb;
   	         		cb.read_func = mread;
            		cb.seek_func = mseek;
            		cb.close_func = mclose;
            		cb.tell_func = mtell;
	       			if(0 != ov_open_callbacks((void *)hmmioSS, &decInfo->oggfile, 0, 0, cb)) {
           	  			free(decInfo);
	            		mmioClose(hmmioSS, 0);
 	           			return MMIO_ERROR;
             		}
            	}
#ifdef DEBUG
				fprintf(file,"Open successfull\n");
#endif
				return MMIO_SUCCESS;
			} else if (pmmioinfo->ulFlags & MMIO_WRITE) {
	       		EncInfo *encInfo = (EncInfo *)malloc(sizeof(EncInfo));
#ifdef DEBUG
			fprintf(file,"File Write: %s\n",pszFileName);
#endif
	       		if (!encInfo) {
  	          		mmioClose(hmmioSS, 0);
            		return MMIO_ERROR;
                }
	       		memset(encInfo, 0, sizeof(EncInfo));
	       		encInfo->t = WRITENUM;
	       		encInfo->hmmioSS = hmmioSS;
				encInfo->vorbisOptions = (PVORBISOPTIONS)pmmioinfo->pExtraInfoStruct;
 	      		pmmioinfo->pExtraInfoStruct = (PVOID)encInfo;
 	      		return MMIO_SUCCESS;
      		}
#ifdef DEBUG
			fprintf(file,"File not read nor write: %s\n",pszFileName);
#endif
      		return MMIO_ERROR;
		}
	    break;                                                 
	case MMIOM_READ: {
		if (!pmmioinfo || !pmmioinfo->pExtraInfoStruct || !lParam1) return MMIO_ERROR;
		
		if (!pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA) {
     		return MMIO_ERROR;
//     		return mmioRead (ogginfo->hmmioSS, (PVOID) lParam1, (ULONG) lParam2);
     	} else {
			OggVorbis_File *oggfile;
			long rc = 0;
			int current_section;
			long total = 0;
			
			oggfile = &((DecInfo *)pmmioinfo->pExtraInfoStruct)->oggfile;
			if (READNUM != ((DecInfo *)pmmioinfo->pExtraInfoStruct)->t) return MMIO_ERROR;
			while (lParam2 > 0) {
	         	rc = ov_read(oggfile, (char *)lParam1, (int)lParam2, 0, 2, 1,  &current_section);
	         	if (rc < 0) {
#ifdef DEBUG
fprintf(file, "Read failed once\n");
#endif
				continue;
				}
				if (rc <= 0) break;
				lParam2 -= rc;
				lParam1 += rc;
				total += rc;
			}
#ifdef DEBUG
fprintf(file,"Read rc:%ld total:%ld\n",rc,total);
#endif
         	if (rc < 0) return MMIO_ERROR;
         	return total;
        }
   	}
	break;
	case MMIOM_SEEK: {
        LONG lPosDesired;
		OggVorbis_File *oggfile;
    	vorbis_info *vi;
		
		if (!pmmioinfo || !pmmioinfo->pExtraInfoStruct) return MMIO_ERROR;
		if (!pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA) return MMIO_ERROR;    	
		
		oggfile = &((DecInfo *)pmmioinfo->pExtraInfoStruct)->oggfile;
		if (READNUM != ((DecInfo *)pmmioinfo->pExtraInfoStruct)->t) return MMIO_ERROR;
		vi = ov_info(oggfile, -1);
		if (!vi) return MMIO_ERROR;
	
		if (SEEK_SET == lParam2) {
     		lPosDesired = lParam1/(2*vi->channels);
        } else if (SEEK_CUR == lParam2) {
            if (0 == lParam1) {
               return ov_pcm_tell(oggfile)*2*vi->channels;
            } /* endif */
           	lPosDesired = ov_pcm_tell(oggfile) + lParam1/(2*vi->channels);
        } else if (SEEK_END == lParam2) {
           	lPosDesired = ov_pcm_total(oggfile,-1) + lParam1/(2*vi->channels);
        } else {
           return MMIO_ERROR;
        }
#ifdef DEBUG
fprintf(file,"Seek to %ld by %d\n",lPosDesired, lParam2);
#endif
		if (ov_pcm_seek(oggfile, lPosDesired) < 0) return MMIO_ERROR;

    	return lPosDesired*2*vi->channels;
	}
    break;

	case MMIOM_CLOSE: {
		int rc;
#ifdef DEBUG
       	    fprintf(file,"start CLOSE\n");
#endif		
		if (!pmmioinfo) return MMIO_ERROR;
		
		if (pmmioinfo->pExtraInfoStruct) {
     		DecInfo *decInfo = (DecInfo *)pmmioinfo->pExtraInfoStruct;
#ifdef DEBUG
       	    fprintf(file,"ready CLOSE\n");
#endif		
			if (READNUM == decInfo->t) {
#ifdef DEBUG
       	    fprintf(file,"read CLOSE\n");
#endif		
     			ov_clear(&decInfo->oggfile);
     			free(decInfo);
     			decInfo = 0;
                rc=MMIO_SUCCESS;
     		} else if (WRITENUM == decInfo->t) {
   	           EncInfo *encInfo = (EncInfo*)pmmioinfo->pExtraInfoStruct;
#ifdef DEBUG
       	    fprintf(file,"write CLOSE\n");
#endif		
			   if (encInfo->headerSet) {
	               vorbis_analysis_wrote(&encInfo->vd,0);
 	               rc = oggWrite(encInfo,1);
	               ogg_stream_clear(&encInfo->os);
	               vorbis_block_clear(&encInfo->vb);
	               vorbis_dsp_clear(&encInfo->vd);
 	               vorbis_comment_clear(&encInfo->vc);
	               vorbis_info_clear(&encInfo->vi);
               }
   	           mmioClose(encInfo->hmmioSS, 0);
  	           free(encInfo);
 	           encInfo = 0;
               rc = MMIO_SUCCESS;
	        } else rc = MMIO_ERROR;
     		pmmioinfo->pExtraInfoStruct = 0;
#ifdef DEBUG
       	    fprintf(file,"CLOSE\n");
#endif		
			return rc;
        }
     	return MMIO_ERROR;
    }
    break;
	case MMIOM_IDENTIFYFILE: {
    	unsigned char buf[4];
		HMMIO hmmioTemp;
		ULONG ulTempFlags = MMIO_READ | MMIO_DENYWRITE | MMIO_NOIDENTIFY;
		LONG rc = MMIO_ERROR;

		if (!lParam1 && !lParam2) return MMIO_ERROR;
    	hmmioTemp = (HMMIO)lParam2;
    	if (!hmmioTemp) {
        	hmmioTemp = mmioOpen((PSZ)lParam1, NULL, ulTempFlags);
        }

		if (hmmioTemp) {
			rc = mmioRead(hmmioTemp, buf, 4);
			if (rc == 4 && buf[0] == 'O' && buf[1] == 'g' &&
					buf[2] == 'g' && buf[3] == 'S') {
				rc = MMIO_SUCCESS;
          	}
			if (!lParam2) mmioClose(hmmioTemp, 0);
		}
		return rc;
	}
    break;
	case MMIOM_GETFORMATINFO: {
    	PMMFORMATINFO pmmformatinfo;
    	pmmformatinfo = (PMMFORMATINFO)lParam1;
    	pmmformatinfo->ulStructLen = sizeof(MMFORMATINFO);
    	pmmformatinfo->fccIOProc = FOURCC_Vorbis;
    	pmmformatinfo->ulIOProcType = MMIO_IOPROC_FILEFORMAT;
    	pmmformatinfo->ulMediaType = MMIO_MEDIATYPE_AUDIO;
    	pmmformatinfo->ulFlags = MMIO_CANREADTRANSLATED 
    	   | MMIO_CANWRITETRANSLATED
           | MMIO_CANSEEKTRANSLATED;
    	strcpy(pmmformatinfo->szDefaultFormatExt, "OGG");
    	pmmformatinfo->ulCodePage = 0;
    	pmmformatinfo->ulLanguage = 0;
    	pmmformatinfo->lNameLength = 21;
    	return MMIO_SUCCESS;
    }
    break;
	case MMIOM_GETFORMATNAME:
		if (lParam2 > 21) { 
     		strcpy((PSZ)lParam1, "Ogg Vorbis");
     		return MMIO_SUCCESS;
     	} else return MMIO_ERROR;
    break;
    case MMIOM_QUERYHEADERLENGTH: return (sizeof (MMAUDIOHEADER));
    break;
	case MMIOM_GETHEADER: {
		OggVorbis_File *oggfile;
		DecInfo *decInfo;
    	PMMAUDIOHEADER mmaudioheader;
    	vorbis_info *vi;
    	
		if (!pmmioinfo || !pmmioinfo->pExtraInfoStruct) return 0;
		if (!(pmmioinfo->ulFlags & MMIO_READ)) return 0;
		decInfo = (DecInfo *)pmmioinfo->pExtraInfoStruct;
		oggfile = &decInfo->oggfile;
		if (READNUM != decInfo->t){
            pmmioinfo->ulErrorRet = MMIOERR_INVALID_STRUCTURE;
            return 0;
        }
		
#ifdef DEBUG
		fprintf(file,"HERE\n");
#endif
		if (!(pmmioinfo->ulTranslate & MMIO_TRANSLATEHEADER) &&
		    !(pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA)) return 0;
		mmaudioheader = (MMAUDIOHEADER *)lParam1;
		if (sizeof(MMAUDIOHEADER) > lParam2) {
            pmmioinfo->ulErrorRet = MMIOERR_INVALID_BUFFER_LENGTH;
			return 0;
		}

#ifdef DEBUG
		fprintf(file,"THERE\n");
#endif

		vi = ov_info(oggfile, -1);
		if (!vi) {
            pmmioinfo->ulErrorRet = MMIOERR_INVALID_STRUCTURE;
            return 0;
        }

		mmaudioheader->ulContentType = MMIO_MIDI_UNKNOWN;
		mmaudioheader->ulMediaType = MMIO_MEDIATYPE_AUDIO;
		mmaudioheader->mmXWAVHeader.WAVEHeader.usFormatTag=DATATYPE_WAVEFORM;
		mmaudioheader->mmXWAVHeader.WAVEHeader.usChannels = vi->channels;
		mmaudioheader->mmXWAVHeader.WAVEHeader.ulSamplesPerSec = vi->rate;
		mmaudioheader->mmXWAVHeader.WAVEHeader.usBitsPerSample = 16;
		mmaudioheader->mmXWAVHeader.WAVEHeader.ulAvgBytesPerSec=
			mmaudioheader->mmXWAVHeader.WAVEHeader.usChannels * 
			mmaudioheader->mmXWAVHeader.WAVEHeader.ulSamplesPerSec *
			mmaudioheader->mmXWAVHeader.WAVEHeader.usBitsPerSample / 8;
		mmaudioheader->mmXWAVHeader.WAVEHeader.usBlockAlign=
			mmaudioheader->mmXWAVHeader.WAVEHeader.usChannels * 
			mmaudioheader->mmXWAVHeader.WAVEHeader.usBitsPerSample / 8;
		mmaudioheader->mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInMS=
			(unsigned long)(ov_time_total(oggfile, -1)*1000.0);
		mmaudioheader->mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes=
		    (unsigned long)ov_pcm_total(oggfile, -1)*
		    mmaudioheader->mmXWAVHeader.WAVEHeader.usBlockAlign;

#ifdef DEBUG
		fprintf(file,"time: %ld size: %ld rate: %ld\n",
			mmaudioheader->mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInMS,
			mmaudioheader->mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes,
			mmaudioheader->mmXWAVHeader.WAVEHeader.ulSamplesPerSec);
	
#endif
		if (0 != decInfo->vorbisOptions && VORBIS_COOKIE == decInfo->vorbisOptions->cookie) {
			decInfo->vorbisOptions->nominal_bitrate = ov_bitrate(oggfile, -1);
			mmaudioheader->mmXWAVHeader.XWAVHeaderInfo.pAdditionalInformation = decInfo->vorbisOptions;
        }
		return (sizeof (MMAUDIOHEADER));
    }
    break;

	case MMIOM_SETHEADER: {
    	EncInfo *encInfo;
    	PMMAUDIOHEADER mmaudioheader;
        int totalout = 0;
        int rc;

		if (!pmmioinfo || !pmmioinfo->pExtraInfoStruct) return 0;
		encInfo = (EncInfo*)pmmioinfo->pExtraInfoStruct;
		if (WRITENUM != encInfo->t) return 0;
#ifdef DEBUG
fprintf(file,"write header: %x, %x, %x\n",!(pmmioinfo->ulFlags & MMIO_WRITE),
	encInfo->headerSet, (!(pmmioinfo->ulTranslate & MMIO_TRANSLATEHEADER) && 
		        !(pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA)));
fprintf(file,"flag: %x, trans: %x\n",pmmioinfo->ulFlags,pmmioinfo->ulTranslate);
#endif
		if (/*!(pmmioinfo->ulFlags & MMIO_WRITE) ||*/ encInfo->headerSet
		    || (!(pmmioinfo->ulTranslate & MMIO_TRANSLATEHEADER) && 
		        !(pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA))) return 0;
		if (!lParam1) {
     		pmmioinfo->ulErrorRet = MMIOERR_INVALID_STRUCTURE;
     		return 0;
     	}
     	mmaudioheader = (PMMAUDIOHEADER)lParam1;
     	if (lParam2 != sizeof(MMAUDIOHEADER)) {
         	pmmioinfo->ulErrorRet = MMIOERR_INVALID_BUFFER_LENGTH;
         	return 0;
        }
		  /********** Encode setup ************/
	if (0 != mmaudioheader->mmXWAVHeader.WAVEHeader.usBitsPerSample%8) {
      /* Bit-rate must be multiple of 8 */
      return 0;
    }
	encInfo->bitsPerSample=mmaudioheader->mmXWAVHeader.WAVEHeader.usBitsPerSample;
#ifdef DEBUG
fprintf(file,"ready to write header: ");
#endif
    vorbis_info_init(&encInfo->vi);
	if (0 == encInfo->vorbisOptions || VORBIS_COOKIE != encInfo->vorbisOptions->cookie) {
#ifdef DEBUG
fprintf(file,"default quality 0.3\n");
#endif
	    rc = vorbis_encode_init_vbr(&encInfo->vi,
	  	mmaudioheader->mmXWAVHeader.WAVEHeader.usChannels,
	  	mmaudioheader->mmXWAVHeader.WAVEHeader.ulSamplesPerSec, 0.3);
    } else {
#ifdef DEBUG
fprintf(file,"bitsPerSample: %d channels: %d samplesPerSec: %ld min: %ld nominal: %ld max: %ld\n",
	encInfo->bitsPerSample,
	  	mmaudioheader->mmXWAVHeader.WAVEHeader.usChannels,
	  	mmaudioheader->mmXWAVHeader.WAVEHeader.ulSamplesPerSec,
	  	encInfo->vorbisOptions->max_bitrate,
	  	encInfo->vorbisOptions->nominal_bitrate,
	  	encInfo->vorbisOptions->min_bitrate);
#endif
	    rc = vorbis_encode_init(&encInfo->vi,
	  	mmaudioheader->mmXWAVHeader.WAVEHeader.usChannels,
	  	mmaudioheader->mmXWAVHeader.WAVEHeader.ulSamplesPerSec,
	  	encInfo->vorbisOptions->max_bitrate,
	  	encInfo->vorbisOptions->nominal_bitrate,
	  	encInfo->vorbisOptions->min_bitrate);
    }

    if (rc) {
#ifdef DEBUG
fprintf(file,"encodeInit failed: %d\n",rc);
#endif
       return 0;
    } /* endif */

  /* add a comment */
  vorbis_comment_init(&encInfo->vc);
  vorbis_comment_add_tag(&encInfo->vc,"ENCODER","mmioVorbis");

  /* set up the analysis state and auxiliary encoding storage */
  vorbis_analysis_init(&encInfo->vd,&encInfo->vi);
  vorbis_block_init(&encInfo->vd,&encInfo->vb);

  /* set up our packet->stream encoder */
  /* pick a random serial number; that way we can more likely build
     chained streams just by concatenation */
  srand(time(NULL));
  ogg_stream_init(&encInfo->os,rand());

  {
    ogg_packet header;
    ogg_packet header_comm;
    ogg_packet header_code;

    vorbis_analysis_headerout(&encInfo->vd,&encInfo->vc,&header,&header_comm,&header_code);
    ogg_stream_packetin(&encInfo->os,&header); /* automatically placed in its own
					 page */
    ogg_stream_packetin(&encInfo->os,&header_comm);
    ogg_stream_packetin(&encInfo->os,&header_code);
	while(1){
		int result=ogg_stream_flush(&encInfo->os,&encInfo->og);
		if(result==0)break;
		result = mmioWrite(encInfo->hmmioSS, encInfo->og.header,encInfo->og.header_len);
        totalout += result;
		if (result!=encInfo->og.header_len) {
	               ogg_stream_clear(&encInfo->os);
	               vorbis_block_clear(&encInfo->vb);
	               vorbis_dsp_clear(&encInfo->vd);
 	               vorbis_comment_clear(&encInfo->vc);
	               vorbis_info_clear(&encInfo->vi);
			return 0;
        }
		result = mmioWrite(encInfo->hmmioSS, encInfo->og.body,encInfo->og.body_len);
        totalout += result;
		if (result!=encInfo->og.body_len) {
	               ogg_stream_clear(&encInfo->os);
	               vorbis_block_clear(&encInfo->vb);
	               vorbis_dsp_clear(&encInfo->vd);
 	               vorbis_comment_clear(&encInfo->vc);
	               vorbis_info_clear(&encInfo->vi);
			return 0;
		}
	}
  }
  		encInfo->headerSet = 1;
  		return totalout;
    }
    break;
	case MMIOM_WRITE: {
    	EncInfo *encInfo;
		if (!pmmioinfo || !pmmioinfo->pExtraInfoStruct) return MMIO_ERROR;
		encInfo = (EncInfo*)pmmioinfo->pExtraInfoStruct;
		if (WRITENUM != encInfo->t) return MMIO_ERROR;
		if (!encInfo->headerSet) return MMIO_ERROR;
		if (!(pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA)) {
     		if (!lParam1) return MMIO_ERROR;
     		return mmioWrite(encInfo->hmmioSS, (PVOID)lParam1, lParam2);
     	} else {
            if (lParam2 == 0) {
                vorbis_analysis_wrote(&encInfo->vd,0);
            } else {
                long i;
				int j, k;
                int num;
				float denom = 1;
                signed char *readbuffer = (char *)lParam1;
                /* data to encode */
                /* expose the buffer to submit data */
				int sampleSize = encInfo->vi.channels*encInfo->bitsPerSample/8;
				int samples = lParam2/sampleSize;
	            float **buffer=vorbis_analysis_buffer(&encInfo->vd, samples);
#ifdef DEBUG
fprintf(file,"write: %ld\n",lParam2);
#endif

  	            /* :TODO: Work with buffers not a multiple of sampleSize*/
                if (lParam2 % sampleSize != 0) {
#ifdef DEBUG
fprintf(file,"Bad Write Buffer Size\n");
#endif
                    return MMIO_ERROR;
                }
                for(i=0;i<samples;i++){
                   for (j=0;j<encInfo->vi.channels;j++) {
                    num=0; denom=0.5;
					if (encInfo->bitsPerSample<=8) {
        				buffer[j][i]=(float)((unsigned char)(readbuffer[i*sampleSize])-
							(1<<(encInfo->bitsPerSample-1)))/
							(float)(1<<(encInfo->bitsPerSample-1));
					} else {
						for (k=encInfo->bitsPerSample/8;k>0;k--) {
							if (k==encInfo->bitsPerSample/8) {
								num=(readbuffer[i*sampleSize+k-1]);
							} else {
								num=(num<<8)|((0xff)&(int)(readbuffer[i*sampleSize+k-1]));
    		    			}
							denom *= 256.0;
						}
 	                   buffer[j][i]=((float)num)/denom;
					}
                   } /* endfor */
                }
                vorbis_analysis_wrote(&encInfo->vd,i);
            } /* endif */
            if (oggWrite(encInfo,0)>=0) {
                return lParam2;
            } else {
                return MMIO_ERROR;
            } /* endif */
        }
    }
    break;
#ifdef DEBUG
	case MMIOM_TEMPCHANGE: {
        return MMIO_SUCCESS;
    }
    break;
#endif
	}
#ifdef DEBUG	
	fprintf(file,"unexpected command: %x\n",usMsg);
#endif
	return MMIOERR_UNSUPPORTED_MESSAGE;
}
Exemple #12
0
int main(){
  ogg_stream_state os; /* take physical pages, weld into a logical
                          stream of packets */
  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 */

  int eos=0,ret;
  int i, founddata;
  int numReads=0;
    
    FILE *outFile = fopen("../test.ogg","wb");

  /* we cheat on the WAV header; we just bypass 44 bytes (simplest WAV
     header is 44 bytes) and assume that the data is 44.1khz, stereo, 16 bit
     little endian pcm samples. This is just an example, after all. */

  /********** Encode setup ************/

  vorbis_info_init(&vi);

  /* choose an encoding mode.  A few possibilities commented out, one
     actually used: */

  /*********************************************************************
   Encoding using a VBR quality mode.  The usable range is -.1
   (lowest quality, smallest file) to 1. (highest quality, largest file).
   Example quality mode .4: 44kHz stereo coupled, roughly 128kbps VBR

   ret = vorbis_encode_init_vbr(&vi,2,44100,.4);

   ---------------------------------------------------------------------

   Encoding using an average bitrate mode (ABR).
   example: 44kHz stereo coupled, average 128kbps VBR

   ret = vorbis_encode_init(&vi,2,44100,-1,128000,-1);

   ---------------------------------------------------------------------

   Encode using a quality mode, but select that quality mode by asking for
   an approximate bitrate.  This is not ABR, it is true VBR, but selected
   using the bitrate interface, and then turning bitrate management off:

   ret = ( vorbis_encode_setup_managed(&vi,2,44100,-1,128000,-1) ||
           vorbis_encode_ctl(&vi,OV_ECTL_RATEMANAGE2_SET,NULL) ||
           vorbis_encode_setup_init(&vi));

   *********************************************************************/

  ret=vorbis_encode_init_vbr(&vi,2,44100,1.0);

  /* do not continue if setup failed; this can happen if we ask for a
     mode that libVorbis does not support (eg, too low a bitrate, etc,
     will return 'OV_EIMPL') */

  if(ret)exit(1);

  /* add a comment */
  vorbis_comment_init(&vc);
  vorbis_comment_add_tag(&vc,"ENCODER","encoder_example.c");

  /* set up the analysis state and auxiliary encoding storage */
  vorbis_analysis_init(&vd,&vi);
  vorbis_block_init(&vd,&vb);

  /* set up our packet->stream encoder */
  /* pick a random serial number; that way we can more likely build
     chained streams just by concatenation */
  srand(time(NULL));
  ogg_stream_init(&os,rand());

  /* Vorbis streams begin with three headers; the initial header (with
     most of the codec setup parameters) which is mandated by the Ogg
     bitstream spec.  The second header holds any comment fields.  The
     third header holds the bitstream codebook.  We merely need to
     make the headers, then pass them to libvorbis one at a time;
     libvorbis handles the additional Ogg bitstream constraints */

  {
    ogg_packet header;
    ogg_packet header_comm;
    ogg_packet header_code;

    vorbis_analysis_headerout(&vd,&vc,&header,&header_comm,&header_code);
    ogg_stream_packetin(&os,&header); /* automatically placed in its own
                                         page */
    ogg_stream_packetin(&os,&header_comm);
    ogg_stream_packetin(&os,&header_code);

    /* This ensures the actual
     * audio data will start on a new page, as per spec
     */
    while(!eos){
      int result=ogg_stream_flush(&os,&og);
      if(result==0)break;
      fwrite(og.header,1,og.header_len,outFile);
      fwrite(og.body,1,og.body_len,outFile);
    }

  }

  while(!eos){
    long i;
    long bytes=READ*4; /* stereo hardwired here */
    numReads++;

    if(numReads>10000) bytes=0;

    if(bytes==0){
      /* end of file.  this can be done implicitly in the mainline,
         but it's easier to see here in non-clever fashion.
         Tell the library we're at end of stream so that it can handle
         the last frame and mark end of stream in the output properly */
      vorbis_analysis_wrote(&vd,0);

    }else{
      /* data to encode */

      /* expose the buffer to submit data */
      float **buffer=vorbis_analysis_buffer(&vd,READ);

      /* uninterleave samples */
      for(i=0;i<bytes/4;i++){
	static float curamp = 0;
	curamp += 0.15f;
	buffer[0][i] = sinf(curamp);
	buffer[1][i] = sinf(curamp);
      }



      /* tell the library how much we actually submitted */
      vorbis_analysis_wrote(&vd,i);
    }

    /* vorbis does some data preanalysis, then divvies up blocks for
       more involved (potentially parallel) processing.  Get a single
       block for encoding now */
    while(vorbis_analysis_blockout(&vd,&vb)==1){

      /* analysis, assume we want to use bitrate management */
      vorbis_analysis(&vb,NULL);
      vorbis_bitrate_addblock(&vb);

      while(vorbis_bitrate_flushpacket(&vd,&op)){

        /* weld the packet into the bitstream */
        ogg_stream_packetin(&os,&op);

        /* write out pages (if any) */
        while(!eos){
          int result=ogg_stream_pageout(&os,&og);
          if(result==0)break;
          fwrite(og.header,1,og.header_len,outFile);
          fwrite(og.body,1,og.body_len,outFile);

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

  /* clean up and exit.  vorbis_info_clear() must be called last */

  ogg_stream_clear(&os);
  vorbis_block_clear(&vb);
  vorbis_dsp_clear(&vd);
  vorbis_comment_clear(&vc);
  vorbis_info_clear(&vi);

  /* ogg_page and ogg_packet structs always point to storage in
     libvorbis.  They're never freed or manipulated directly */

  fprintf(stderr,"Done.\n");
  return(0);
}
Exemple #13
0
DEFINE_CONSTRUCTOR() {

	Private *pv = NULL;

	JL_DEFINE_ARGS;
	JL_ASSERT_CONSTRUCTING();
	JL_DEFINE_CONSTRUCTOR_OBJ;
	JL_ASSERT_ARGC_RANGE(0,3);
	
	pv = static_cast<Private*>(jl_malloc(sizeof(Private)));
	JL_SetPrivate(JL_OBJ, pv);

	long channels = jl::getValueDefault(cx, JL_SARG(1), 2L);
	long rate = jl::getValueDefault(cx, JL_SARG(2), 44100L);
	float quality = jl::getValueDefault(cx, JL_SARG(3), 0.f);


//	JL_ASSERT_RANGE(quality, -0.1f, 1.0f, "quality");

	vorbis_info_init(&pv->vi);
	int st;
	
	//st = vorbis_encode_setup_vbr(&pv->vi, 2, 44100, 0.);
	// st = vorbis_encode_setup_init(&pv->vi);
	//vorbis_encode_ctl(&pv->vi, 


	vorbis_encode_ctl(&pv->vi, OV_ECTL_RATEMANAGE_SET, NULL);

	// VBR
	st = vorbis_encode_init_vbr(&pv->vi, channels, rate, quality);
	ASSERT( st == 0 );


/*
	// CBR/ABR
	st = vorbis_encode_init(&pv->vi, channels, rate, 64 *1024, 96 *1024, 128 *1024);
	ASSERT( st == 0 );
*/

//	st = vorbis_encode_ctl(&pv->vi, OV_ECTL_RATEMANAGE2_SET, NULL);
//	ASSERT( st == 0 );


	st = vorbis_analysis_init(&pv->vds, &pv->vi);
	ASSERT( st == 0 );


	st = vorbis_block_init(&pv->vds, &pv->vb);
	ASSERT( st == 0 );


	// ogg stream

	srand((unsigned)time(NULL));
	st = ogg_stream_init(&pv->oss, rand());
	ASSERT( st == 0 );

	ogg_packet header;
	ogg_packet header_comm;
	ogg_packet header_code;

	vorbis_comment vc;
	vorbis_comment_init(&vc);
	//vorbis_comment_add_tag(&vc, "ENCODER", "jslibs");

	st = vorbis_analysis_headerout(&pv->vds, &vc, &header, &header_comm, &header_code);
	ASSERT( st == 0 );

	st = ogg_stream_packetin(&pv->oss, &header);
	ASSERT( st == 0 );

	st = ogg_stream_packetin(&pv->oss, &header_comm);
	ASSERT( st == 0 );

	st = ogg_stream_packetin(&pv->oss, &header_code);
	ASSERT( st == 0 );

/*
	for (;;) {
		
		int flushStatus = ogg_stream_flush(&pv->oss, &pv->op);
		if( flushStatus == 0 )
			break;
	}

	dstBuf.Write(pv->op.header, pv->op.header_len);
	dstBuf.Write(pv->op.body, pv->op.body_len);
*/





	return true;
bad:
	jl_free(pv);
	return false;
}
/*!
 * \brief Create a new OGG/Vorbis filestream and set it up for writing.
 * \param fd File descriptor that points to on-disk storage.
 * \param comment Comment that should be embedded in the OGG/Vorbis file.
 * \return A new filestream.
 */
static struct cw_filestream *ogg_vorbis_rewrite(FILE *fp, const char *comment)
{
    ogg_packet header;
    ogg_packet header_comm;
    ogg_packet header_code;
    struct cw_filestream *tmp;

    if ((tmp = malloc(sizeof(struct cw_filestream))))
    {
        memset(tmp, 0, sizeof(struct cw_filestream));

        tmp->writing = 1;
        tmp->fp = fp;

        vorbis_info_init(&tmp->vi);

        if (vorbis_encode_init_vbr(&tmp->vi, 1, 8000, 0.4))
        {
            cw_log(LOG_ERROR, "Unable to initialize Vorbis encoder!\n");
            free(tmp);
            return NULL;
        }

        vorbis_comment_init(&tmp->vc);
        vorbis_comment_add_tag(&tmp->vc, "ENCODER", "CallWeaver");
        if (comment)
            vorbis_comment_add_tag(&tmp->vc, "COMMENT", (char *) comment);

        vorbis_analysis_init(&tmp->vd, &tmp->vi);
        vorbis_block_init(&tmp->vd, &tmp->vb);

        ogg_stream_init(&tmp->os, rand());

        vorbis_analysis_headerout(&tmp->vd, &tmp->vc, &header, &header_comm, &header_code);
        ogg_stream_packetin(&tmp->os, &header);                            
        ogg_stream_packetin(&tmp->os, &header_comm);
        ogg_stream_packetin(&tmp->os, &header_code);

        while (!tmp->eos)
        {
            if (ogg_stream_flush(&tmp->os, &tmp->og) == 0)
                break;
            fwrite(tmp->og.header, 1, tmp->og.header_len, tmp->fp);
            fwrite(tmp->og.body, 1, tmp->og.body_len, tmp->fp);
            if (ogg_page_eos(&tmp->og))
                tmp->eos = 1;
        }

        if (cw_mutex_lock(&ogg_vorbis_lock))
        {
            cw_log(LOG_WARNING, "Unable to lock ogg_vorbis list\n");
            fclose(fp);
            ogg_stream_clear(&tmp->os);
            vorbis_block_clear(&tmp->vb);
            vorbis_dsp_clear(&tmp->vd);
            vorbis_comment_clear(&tmp->vc);
            vorbis_info_clear(&tmp->vi);
            free(tmp);
            return NULL;
        }
        glistcnt++;
        cw_mutex_unlock(&ogg_vorbis_lock);
        cw_update_use_count();
    }
    return tmp;
}
Exemple #15
0
void CDemoVideoRecorder::Init(int Width, int Height, int FPS, int Format, const char *pName)
{
    m_pSound = Kernel()->RequestInterface<ISound>();
    m_FPS = FPS;
    m_ScreenWidth = Width;
    m_ScreenHeight = Height;
    m_Format = Format;

    if (m_Format == IClient::DEMO_RECORD_FORMAT_OGV)
    {
        ogg_stream_init(&m_TheoraOggStreamState, rand());
        ogg_stream_init(&m_VorbisOggStreamState, rand());

        char aBuf[1024];
        if (str_find_rev(pName, "/"))
            str_format(aBuf, sizeof(aBuf), "%s.ogv", str_find_rev(pName, "/"));
        else if (str_find_rev(aBuf, "\\"))
            str_format(aBuf, sizeof(pName), "%s.ogv", str_find_rev(pName, "\\"));
        else
            str_format(aBuf, sizeof(aBuf), "%s.ogv", pName);
        m_OggFile = io_open(aBuf, IOFLAG_WRITE);

        //thread_sleep(10000);
        vorbis_info_init(&m_VorbisEncodingInfo);
        vorbis_encode_init_vbr(&m_VorbisEncodingInfo, 2, g_Config.m_SndRate, 1.0f); //2 ch - samplerate - quality 1
        vorbis_analysis_init(&m_VorbisState, &m_VorbisEncodingInfo);
        vorbis_block_init(&m_VorbisState, &m_VorbisBlock);

        vorbis_comment_init(&m_VorbisComment);
        ogg_packet header;
        ogg_packet header_comm;
        ogg_packet header_code;
        vorbis_analysis_headerout(&m_VorbisState, &m_VorbisComment, &header, &header_comm, &header_code);
        ogg_stream_packetin(&m_VorbisOggStreamState, &header);
        ogg_stream_packetin(&m_VorbisOggStreamState, &header_comm);
        ogg_stream_packetin(&m_VorbisOggStreamState, &header_code);


        th_info_init(&m_TheoraEncodingInfo);
        m_TheoraEncodingInfo.frame_width = m_ScreenWidth+15&~0xF;
        m_TheoraEncodingInfo.frame_height = m_ScreenHeight+15&~0xF;
        m_TheoraEncodingInfo.pic_width = m_ScreenWidth;
        m_TheoraEncodingInfo.pic_height = m_ScreenHeight;
        m_TheoraEncodingInfo.pic_x = m_TheoraEncodingInfo.frame_width - m_ScreenWidth>>1&~1;
        m_TheoraEncodingInfo.pic_y = m_TheoraEncodingInfo.frame_height - m_ScreenHeight>>1&~1;
        m_TheoraEncodingInfo.colorspace = TH_CS_UNSPECIFIED;
        m_TheoraEncodingInfo.fps_numerator = FPS; //fps
        m_TheoraEncodingInfo.fps_denominator = 1;
        m_TheoraEncodingInfo.aspect_numerator = -1;
        m_TheoraEncodingInfo.aspect_denominator = -1;
        m_TheoraEncodingInfo.pixel_fmt = TH_PF_444;
        m_TheoraEncodingInfo.target_bitrate = (int)(64870*(ogg_int64_t)48000>>16);
        m_TheoraEncodingInfo.quality = 32;
        m_TheoraEncodingInfo.keyframe_granule_shift = 0;
        m_pThreoraContext = th_encode_alloc(&m_TheoraEncodingInfo);
        int arg = TH_RATECTL_CAP_UNDERFLOW;
        th_encode_ctl(m_pThreoraContext, TH_ENCCTL_SET_RATE_FLAGS, &arg, sizeof(arg));
        th_comment CommentHeader;
        ogg_packet OggPacket;
        th_comment_init(&CommentHeader);
        mem_zero(&OggPacket, sizeof(OggPacket));


            //Flush
        //Step 1
        th_encode_flushheader(m_pThreoraContext, &CommentHeader, &OggPacket); // first header

        ogg_stream_packetin(&m_TheoraOggStreamState, &OggPacket);
        //
        ogg_page OggPage;
        ogg_stream_pageout(&m_TheoraOggStreamState, &OggPage);
        io_write(m_OggFile, OggPage.header, OggPage.header_len);
        io_write(m_OggFile, OggPage.body, OggPage.body_len);

        while(1)
        {
            ogg_page OggPage;
            if (ogg_stream_flush(&m_VorbisOggStreamState,&OggPage) == 0)
                break;
            io_write(m_OggFile, OggPage.header, OggPage.header_len);
            io_write(m_OggFile, OggPage.body, OggPage.body_len);
        }

        while(th_encode_flushheader(m_pThreoraContext, &CommentHeader, &OggPacket))
        {
            ogg_stream_packetin(&m_TheoraOggStreamState, &OggPacket);
        }

        ogg_stream_flush(&m_TheoraOggStreamState, &OggPage);
        io_write(m_OggFile, OggPage.header, OggPage.header_len);
        io_write(m_OggFile, OggPage.body, OggPage.body_len);
    }
	virtual bool Cook(FName Format, const TArray<uint8>& SrcBuffer, FSoundQualityInfo& QualityInfo, TArray<uint8>& CompressedDataStore) const
	{
		check(Format == NAME_OGG);
#if WITH_OGGVORBIS
		{

			short				ReadBuffer[SAMPLES_TO_READ * SAMPLE_SIZE * 2];

			ogg_stream_state	os;		// take physical pages, weld into a logical stream of packets 
			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
			uint32				i;
			bool				eos;

			// Create a buffer to store compressed data
			CompressedDataStore.Empty();
			FMemoryWriter CompressedData( CompressedDataStore );
			uint32 BufferOffset = 0;

			float CompressionQuality = ( float )( QualityInfo.Quality + VORBIS_QUALITY_MODIFIER ) / 100.0f;
			CompressionQuality = FMath::Clamp( CompressionQuality, -0.1f, 1.0f );

			vorbis_info_init( &vi );

			if( vorbis_encode_init_vbr( &vi, QualityInfo.NumChannels, QualityInfo.SampleRate, CompressionQuality ) )
			{
				return false;
			}

			// add a comment
			vorbis_comment_init( &vc );
			vorbis_comment_add_tag( &vc, "ENCODER", "UnrealEngine4" );

			// set up the analysis state and auxiliary encoding storage
			vorbis_analysis_init( &vd, &vi );
			vorbis_block_init( &vd, &vb );

			// set up our packet->stream encoder
			ogg_stream_init( &os, 0 );

			ogg_packet header;
			ogg_packet header_comm;
			ogg_packet header_code;

			vorbis_analysis_headerout( &vd, &vc, &header, &header_comm, &header_code);
			ogg_stream_packetin( &os, &header );
			ogg_stream_packetin( &os, &header_comm );
			ogg_stream_packetin( &os, &header_code );

			// This ensures the actual audio data will start on a new page, as per spec
			while( true )
			{
				int result = ogg_stream_flush( &os, &og );
				if( result == 0 )
				{
					break;
				}

				CompressedData.Serialize( og.header, og.header_len );
				CompressedData.Serialize( og.body, og.body_len );
			}

			eos = false;
			while( !eos )
			{
				// Read samples
				uint32 BytesToRead = FMath::Min( SAMPLES_TO_READ * QualityInfo.NumChannels * SAMPLE_SIZE, QualityInfo.SampleDataSize - BufferOffset );
				FMemory::Memcpy( ReadBuffer, SrcBuffer.GetTypedData() + BufferOffset, BytesToRead );
				BufferOffset += BytesToRead;

				if( BytesToRead == 0)
				{
					// end of file
					vorbis_analysis_wrote( &vd, 0 );
				}
				else
				{
					// expose the buffer to submit data
					float **buffer = vorbis_analysis_buffer( &vd, SAMPLES_TO_READ );

					if( QualityInfo.NumChannels == 1 )
					{
						for( i = 0; i < BytesToRead / SAMPLE_SIZE; i++ )
						{
							buffer[0][i] = ( ReadBuffer[i] ) / 32768.0f;
						}
					}
					else
					{
						for( i = 0; i < BytesToRead / ( SAMPLE_SIZE * 2 ); i++ )
						{
							buffer[0][i] = ( ReadBuffer[i * 2] ) / 32768.0f;
							buffer[1][i] = ( ReadBuffer[i * 2 + 1] ) / 32768.0f;
						}
					}

					// tell the library how many samples we actually submitted
					vorbis_analysis_wrote( &vd, i );
				}

				// vorbis does some data preanalysis, then divvies up blocks for more involved (potentially parallel) processing.
				while( vorbis_analysis_blockout( &vd, &vb ) == 1 )
				{
					// analysis, assume we want to use bitrate management
					vorbis_analysis( &vb, NULL );
					vorbis_bitrate_addblock( &vb );

					while( vorbis_bitrate_flushpacket( &vd, &op ) )
					{
						// weld the packet into the bitstream
						ogg_stream_packetin( &os, &op );

						// write out pages (if any)
						while( !eos )
						{
							int result = ogg_stream_pageout( &os, &og );
							if( result == 0 )
							{
								break;
							}
							CompressedData.Serialize( og.header, og.header_len );
							CompressedData.Serialize( og.body, og.body_len );

							// 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 = true;
							}
						}
					}
				}
			}

			// clean up and exit.  vorbis_info_clear() must be called last
			ogg_stream_clear( &os );
			vorbis_block_clear( &vb );
			vorbis_dsp_clear( &vd );
			vorbis_comment_clear( &vc );
			vorbis_info_clear( &vi );
			// ogg_page and ogg_packet structs always point to storage in libvorbis.  They're never freed or manipulated directly
		}
		return CompressedDataStore.Num() > 0;
#else
		return false;
#endif		// WITH_OGGVOBVIS
	}
Exemple #17
0
int audev_init_device(char *devname, long ratewanted, int verbose, extraopt_t *extra)
{
  int ret;
  int channels, format, rate;
  int fragsize;
  extraopt_t *opt;
  double maxsecs = 5.0;
  double quality = 0.5;
  char *title = NULL;

  if (verbose) {
    printf("Boodler: VORBIS sound driver.\n");
  }

  if (device) {
    fprintf(stderr, "Sound device is already open.\n");
    return FALSE;
  }

  format = FALSE; /* always little-endian */

  for (opt=extra; opt->key; opt++) {
    if (!strcmp(opt->key, "time") && opt->val) {
      maxsecs = atof(opt->val);
    }
    else if (!strcmp(opt->key, "quality") && opt->val) {
      quality = atof(opt->val);
    }
    else if (!strcmp(opt->key, "title") && opt->val) {
      title = opt->val;
    }
    else if (!strcmp(opt->key, "listdevices")) {
      printf("Device list: give any writable file as a device name.\n");
    }
  }

  if (!ratewanted)
    ratewanted = DEFAULT_SOUNDRATE;
  if (!devname) 
    devname = DEFAULT_FILENAME;

  device = fopen(devname, "wb");
  if (!device) {
    fprintf(stderr, "Error opening file %s\n", devname);
    return FALSE;
  }

  if (verbose) {
    printf("Opened file %s.\n", devname);
  }

  rate = ratewanted;
  channels = 2;
  fragsize = 16384;

  if (verbose) {
    printf("%d channels, %d frames per second, 16-bit samples (signed, %s)\n",
      channels, rate, (format?"big-endian":"little-endian"));
    printf("vorbis VBR encoding quality %f\n", quality);
  }

  maxtime = (long)(maxsecs * (double)rate);
  curtime = 0;
  if (verbose) {
    printf("%g seconds of output (%ld frames)\n", maxsecs, maxtime);
  }

  sound_rate = rate;
  sound_channels = channels;
  sound_format = format;
  sound_buffersize = fragsize;

  samplesperbuf = sound_buffersize / 2;
  framesperbuf = sound_buffersize / (2 * sound_channels);

  rawbuffer = (char *)malloc(sound_buffersize);
  if (!rawbuffer) {
    fprintf(stderr, "Unable to allocate sound buffer.\n");
    fclose(device);
    device = NULL;
    return FALSE;    
  }

  valbuffer = (long *)malloc(sizeof(long) * samplesperbuf);
  if (!valbuffer) {
    fprintf(stderr, "Unable to allocate sound buffer.\n");
    free(rawbuffer);
    rawbuffer = NULL;
    fclose(device);
    device = NULL;
    return FALSE;     
  }
  
  vorbis_info_init(&vi);
  ret = vorbis_encode_init_vbr(&vi, 2, sound_rate, quality);
  if (ret) {
    fprintf(stderr, "Unable to initialize Vorbis encoder.\n");
    free(valbuffer);
    valbuffer = NULL;
    free(rawbuffer);
    rawbuffer = NULL;
    fclose(device);
    device = NULL;
    return FALSE;
  }

  /* See <http://xiph.org/vorbis/doc/v-comment.html> */  
  vorbis_comment_init(&vc);
  {
    char commentbuf[256];
    time_t nowtime;
    struct tm *now;

    if (title) {
      strcpy(commentbuf, "Boodler: ");
      strncat(commentbuf, title, 255-strlen(commentbuf));
      vorbis_comment_add_tag(&vc, "TITLE", commentbuf);
    }

    nowtime = time(NULL);
    now = localtime(&nowtime);
    strftime(commentbuf, 255, "%Y-%m-%d (generated)", now);
    vorbis_comment_add_tag(&vc, "DATE", commentbuf);

    vorbis_comment_add_tag(&vc, "ENCODER", "Boodler");
  }
  
  vorbis_analysis_init(&vd, &vi);
  vorbis_block_init(&vd, &vb);
  
  srand(time(NULL));
  ret = ogg_stream_init(&os, rand());
  if (ret) {
    fprintf(stderr, "Unable to initialize Ogg stream.\n");
    free(valbuffer);
    valbuffer = NULL;
    free(rawbuffer);
    rawbuffer = NULL;
    fclose(device);
    device = NULL;
    return FALSE;
  }
  
  {
    ogg_packet header;
    ogg_packet header_comm;
    ogg_packet header_code;

    vorbis_analysis_headerout(&vd, &vc, &header, &header_comm, &header_code);
    ogg_stream_packetin(&os, &header);
    ogg_stream_packetin(&os, &header_comm);
    ogg_stream_packetin(&os, &header_code);
    while (!eos) {
      int result = ogg_stream_flush(&os, &og);
      if (result==0) break;
      fwrite(og.header, 1, og.header_len, device);
      fwrite(og.body, 1, og.body_len, device);
    }
  }

  return TRUE;
}
Exemple #18
0
krad_vorbis_t *krad_vorbis_encoder_create (int channels,
                                           int sample_rate,
                                           float quality) {

  int ret;
  int pos;
  krad_vorbis_t *vorbis;
  ogg_packet header_main;
  ogg_packet header_comments;
  ogg_packet header_codebooks;

  vorbis = calloc (1, sizeof(krad_vorbis_t));

  pos = 0;

  vorbis->error = 0;
  vorbis->state_str = "";

  vorbis->channels = channels;
  vorbis->sample_rate = sample_rate;
  vorbis->quality = quality;

  vorbis_info_init (&vorbis->vinfo);

  printk ("KR Vorbis Encoder Version: %s", vorbis_version_string());

  ret = vorbis_encode_init_vbr (&vorbis->vinfo,
                                vorbis->channels,
                                vorbis->sample_rate,
                                vorbis->quality);
  if (ret < 0) {
    vorbis->error = ret;
    vorbis->state_str = "Krad Vorbis Encoder: vorbis_encode_init_vbr fail";
    if (ret == OV_EIMPL) {
      vorbis->state_str = "Krad Vorbis Encoder: vorbis mode not supported";
    }
    if (ret == OV_EINVAL) {
      vorbis->state_str = "Krad Vorbis Encoder: illegal vorbis mode";
    }
    printke (vorbis->state_str);
    return vorbis;
  }

  vorbis->small_blocksz = vorbis_info_blocksize (&vorbis->vinfo, 0);
  vorbis->large_blocksz = vorbis_info_blocksize (&vorbis->vinfo, 1);

  printk ("KR Vorbis Encoder Setup: Channels %d Sample Rate: %d Quality: %f",
          vorbis->channels, vorbis->sample_rate, vorbis->quality);

  printk ("KR Vorbis Encoder Setup: Small Block Size: %u Large Block Size: %u",
          vorbis->small_blocksz, vorbis->large_blocksz);

  vorbis_analysis_init (&vorbis->vdsp, &vorbis->vinfo);
  vorbis_block_init (&vorbis->vdsp, &vorbis->vblock);
  vorbis_comment_init (&vorbis->vc);

#ifdef KR_VERSION_STR_FULL
  vorbis_comment_add_tag (&vorbis->vc, "ENCODER", KR_VERSION_STR_FULL);
#endif

  vorbis->header.codec = VORBIS;
  vorbis_analysis_headerout (&vorbis->vdsp,
                             &vorbis->vc,
                             &header_main,
                             &header_comments,
                             &header_codebooks);

  vorbis->hdrdata[0] = 0x02;
  vorbis->hdrdata[1] = (char)header_main.bytes;
  vorbis->hdrdata[2] = (char)header_comments.bytes;

  pos = 3;

  memcpy (vorbis->hdrdata + pos,
          header_main.packet,
          header_main.bytes);

  vorbis->header.data[0] = vorbis->hdrdata + pos;
  vorbis->header.sz[0] = header_main.bytes;
  pos += header_main.bytes;

  memcpy (vorbis->hdrdata + pos,
          header_comments.packet,
          header_comments.bytes);

  vorbis->header.data[1] = vorbis->hdrdata + pos;
  vorbis->header.sz[1] = header_comments.bytes;
  pos += header_comments.bytes;

  memcpy (vorbis->hdrdata + pos,
          header_codebooks.packet,
          header_codebooks.bytes);

  vorbis->header.data[2] = vorbis->hdrdata + pos;
  vorbis->header.sz[2] = header_codebooks.bytes;
  pos += header_codebooks.bytes;

  //vorbis->header.header_combined = vorbis->hdrdata;
  //vorbis->header.header_combined_size = pos;
  vorbis->header.count = 3;

  if (1) {
    printk ("KR Vorbis Encoder Setup: header test start");
    krad_vorbis_test_headers (&vorbis->header);
    printk ("KR Vorbis Encoder Setup: header test end");
  }

  vorbis->state_str = "Krad Vorbis Encoder: Init OK";

  return vorbis;
}
tbool CVorbisEncoder::Process_Init_Descendant()
{
	// Setup encoder
	vorbis_info_init(&vi);
	//mfQuality = -0.1;
	if (vorbis_encode_init_vbr(&vi, miOutputChannels, miInputSampleFreq, mfQuality) != 0) {
		AppendErrMsg("Function vorbis_encode_init_vbr failed for unknown reason.");
		return false;
	}
	// Note: Using vorbis_encode_init rather than vorbis_encode_init_vbr makes encoding 4 times slower
	// because it will try harder at targetting the bitrate you ask of it.
	// Also I think the guy with the unpronouncable name that tuned vorbis (the aoTuV versions)
	// only bothered to optimize the "_vbr" method.. and that's quite ok.
	// Lasse
	//
	//if (vorbis_encode_init(&vi, miOutputChannels, miInputSampleFreq, 256000, 192000, 32000) != 0) {
	//	AppendErrMsg("Function vorbis_encode_init(..) failed for unknown reason.");
	//	return false;
	//}

	// TODO: add comments
	vorbis_comment_init(&vc);
	vorbis_comment_add_tag(&vc,"ENCODER","Koblo 1.0 // aoTuV b5");
	vorbis_comment_add_tag(&vc,"KOBLO_ENC_QUAL", (char*)GetQualityName(meQuality));
	
	/* set up the analysis state and auxiliary encoding storage */
	vorbis_analysis_init(&vd,&vi);
	vorbis_block_init(&vd,&vb);
	
	/* set up our packet->stream encoder */
	/* pick a random serial number; that way we can more likely build
		chained streams just by concatenation */
	srand((unsigned)time(NULL));
	ogg_stream_init(&os,rand());
	
	/* Vorbis streams begin with three headers; the initial header (with
		most of the codec setup parameters) which is mandated by the Ogg
		bitstream spec.  The second header holds any comment fields.  The
		third header holds the bitstream codebook.  We merely need to
		make the headers, then pass them to libvorbis one at a time;
		libvorbis handles the additional Ogg bitstream constraints */
	
	{
		ogg_packet header;
		ogg_packet header_comm;
		ogg_packet header_code;
		
		vorbis_analysis_headerout(&vd,&vc,&header,&header_comm,&header_code);
		ogg_stream_packetin(&os,&header); /* automatically placed in its own
			page */
		ogg_stream_packetin(&os,&header_comm);
		ogg_stream_packetin(&os,&header_code);
		
		/* This ensures the actual
			* audio data will start on a new page, as per spec
			*/
		while(1){
			int result=ogg_stream_flush(&os,&og);
			if(result==0)break;
			//fwrite(og.header,1,og.header_len,stdout);
			//fwrite(og.body,1,og.body_len,stdout);
			WriteOutput((char*)og.header, og.header_len);
			WriteOutput((char*)og.body, og.body_len);
		}
	}

	return true;
} // Process_Init_Secendant
/*------------------------------------------------------------------------------
 *  Open an encoding session
 *----------------------------------------------------------------------------*/
bool
VorbisLibEncoder :: open ( void )
                                                            throw ( Exception )
{
    int     ret;

    if ( isOpen() ) {
        close();
    }

    vorbis_info_init( &vorbisInfo);

    if ( isVBR() ) {

        if ( (ret = vorbis_encode_init_vbr( &vorbisInfo,
                                            getInChannel(),
                                            getOutSampleRate(),
                                            getOutQuality() )) ) {
            throw Exception( __FILE__, __LINE__,
                             "vorbis encode init error", ret);
        }
    } else {
#ifdef VORBIS_LIB_RC3
        if ( (ret = vorbis_encode_init( &vorbisInfo,
                                        getInChannel(),
                                        getOutSampleRate(),
                                        getOutBitrate() * 1024,
                                        getOutBitrate() * 1024,
                                        -1 )) ) {
            throw Exception( __FILE__, __LINE__,
                             "vorbis encode init error", ret);
        }
#else
        if ( (ret = vorbis_encode_init( &vorbisInfo,
                                        getInChannel(),
                                        getOutSampleRate(),
                                        -1,
                                        getOutBitrate() * 1024,
                                        -1 )) ) {
            throw Exception( __FILE__, __LINE__,
                             "vorbis encode init error", ret);
        }
#endif
    }

    if ( (ret = vorbis_analysis_init( &vorbisDspState, &vorbisInfo)) ) {
        throw Exception( __FILE__, __LINE__, "vorbis analysis init error", ret);
    }

    if ( (ret = vorbis_block_init( &vorbisDspState, &vorbisBlock)) ) {
        throw Exception( __FILE__, __LINE__, "vorbis block init error", ret);
    }

    if ( (ret = ogg_stream_init( &oggStreamState, 0)) ) {
        throw Exception( __FILE__, __LINE__, "ogg stream init error", ret);
    }

    // open the underlying sink
    if ( !sink->open() ) {
        throw Exception( __FILE__, __LINE__,
                         "vorbis lib opening underlying sink error");
    }

    // create an empty vorbis_comment structure
    vorbis_comment_init( &vorbisComment);

    // create the vorbis stream headers and send them to the underlying sink
    ogg_packet      header;
    ogg_packet      commentHeader;
    ogg_packet      codeHeader;

    if ( (ret = vorbis_analysis_headerout( &vorbisDspState,
                                           &vorbisComment,
                                           &header,
                                           &commentHeader,
                                           &codeHeader )) ) {
        throw Exception( __FILE__, __LINE__, "vorbis header init error", ret);
    }

    ogg_stream_packetin( &oggStreamState, &header);
    ogg_stream_packetin( &oggStreamState, &commentHeader);
    ogg_stream_packetin( &oggStreamState, &codeHeader);

    ogg_page        oggPage;
    while ( ogg_stream_flush( &oggStreamState, &oggPage) ) {
        sink->write( oggPage.header, oggPage.header_len);
        sink->write( oggPage.body, oggPage.body_len);
    }

    vorbis_comment_clear( &vorbisComment );

    // initialize the resampling coverter if needed
    if ( converter ) {
        converter->initialize( resampleRatio, getInChannel());
    }

    encoderOpen = true;

    return true;
}
Exemple #21
0
int Encode_Ogg(void *stream,void(*writefunc)(void *bytes,int count,void *stream),int freq,int channels,float *samples,int length,float compression) {

    oggwriter *ogg;
    int eos;
    int result;

    ogg=(oggwriter*)malloc(sizeof(oggwriter));

    vorbis_info_init(&ogg->vi);

    result=vorbis_encode_init_vbr(&ogg->vi,channels,freq,compression);

    if(result) return -1;	//error format not supported...

// add a comment

    vorbis_comment_init(&ogg->vc);
    vorbis_comment_add_tag(&ogg->vc,"ENCODER","encoder_example.c");

// set up the analysis state and auxiliary encoding storage

    vorbis_analysis_init(&ogg->vd,&ogg->vi);

    vorbis_block_init(&ogg->vd,&ogg->vb);

    srand(time(NULL));
    ogg_stream_init(&ogg->os,rand());

    ogg_packet header;
    ogg_packet header_comm;
    ogg_packet header_code;

    vorbis_analysis_headerout(&ogg->vd,&ogg->vc,&header,&header_comm,&header_code);
    ogg_stream_packetin(&ogg->os,&header); //automatically placed in its own page
    ogg_stream_packetin(&ogg->os,&header_comm);
    ogg_stream_packetin(&ogg->os,&header_code);

//This ensures the actual audio data will start on a new page, as per spec
    while(1) {
        result=ogg_stream_flush(&ogg->os,&ogg->og);
        if(result==0)break;
        writefunc(ogg->og.header,ogg->og.header_len,stream);
        writefunc(ogg->og.body,ogg->og.body_len,stream);
    }

    int i,c,n;
    eos=0;

    while(!eos) {
        if (length>0) {
            float **buffer=vorbis_analysis_buffer(&ogg->vd,READ);
            n=length;
            if (n>READ) n=READ;
//uninterleave samples
            for (i=0; i<n; i++) {
                for (c=0; c<channels; c++) {
                    buffer[c][i]=*samples++;
                }
            }
            length=length-n;
//tell the library how much we actually submitted
            vorbis_analysis_wrote(&ogg->vd,i);
        } else {
            vorbis_analysis_wrote(&ogg->vd,0);
        }
        while(vorbis_analysis_blockout(&ogg->vd,&ogg->vb)==1) {
//analysis, assume we want to use bitrate management
            vorbis_analysis(&ogg->vb,NULL);
            vorbis_bitrate_addblock(&ogg->vb);
            while(vorbis_bitrate_flushpacket(&ogg->vd,&ogg->op)) {
//weld the packet into the bitstream
                ogg_stream_packetin(&ogg->os,&ogg->op);
//write out pages (if any)
                while(!eos) {
                    result=ogg_stream_pageout(&ogg->os,&ogg->og);
                    if(result==0)break;
                    writefunc(ogg->og.header,ogg->og.header_len,stream);
                    writefunc(ogg->og.body,ogg->og.body_len,stream);
                    if (ogg_page_eos(&ogg->og)) eos=1;
                }
            }
        }
    }
//clean up and exit.  vorbis_info_clear() must be called last
    ogg_stream_clear(&ogg->os);
    vorbis_block_clear(&ogg->vb);
    vorbis_dsp_clear(&ogg->vd);
    vorbis_comment_clear(&ogg->vc);
    vorbis_info_clear(&ogg->vi);

    free(ogg);

    return 0;
}
Exemple #22
0
bool ExportOGG(AudacityProject *project,
               bool stereo, wxString fName,
               bool selectionOnly, double t0, double t1)
{
    double    rate    = project->GetRate();
    wxWindow  *parent = project;
    TrackList *tracks = project->GetTracks();
    double    quality = (gPrefs->Read("/FileFormats/OggExportQuality", 50)/(float)100.0);

    wxLogNull logNo;            // temporarily disable wxWindows error messages
    bool      cancelling = false;
    int       eos = 0;

    wxFFile outFile(fName, "wb");

    if(!outFile.IsOpened()) {
        wxMessageBox(_("Unable to open target file for writing"));
        return false;
    }

    // All the Ogg and Vorbis encoding data
    ogg_stream_state stream;
    ogg_page         page;
    ogg_packet       packet;

    vorbis_info      info;
    vorbis_comment   comment;
    vorbis_dsp_state dsp;
    vorbis_block     block;

    // Encoding setup
    vorbis_info_init(&info);
    vorbis_encode_init_vbr(&info, stereo ? 2 : 1, int(rate + 0.5), quality);

    vorbis_comment_init(&comment);
    // If we wanted to add comments, we would do it here

    // Set up analysis state and auxiliary encoding storage
    vorbis_analysis_init(&dsp, &info);
    vorbis_block_init(&dsp, &block);

    // Set up packet->stream encoder.  According to encoder example,
    // a random serial number makes it more likely that you can make
    // chained streams with concatenation.
    srand(time(NULL));
    ogg_stream_init(&stream, rand());

    // First we need to write the required headers:
    //    1. The Ogg bitstream header, which contains codec setup params
    //    2. The Vorbis comment header
    //    3. The bitstream codebook.
    //
    // After we create those our responsibility is complete, libvorbis will
    // take care of any other ogg bistream constraints (again, according
    // to the example encoder source)
    ogg_packet bitstream_header;
    ogg_packet comment_header;
    ogg_packet codebook_header;

    vorbis_analysis_headerout(&dsp, &comment, &bitstream_header, &comment_header,
                              &codebook_header);

    // Place these headers into the stream
    ogg_stream_packetin(&stream, &bitstream_header);
    ogg_stream_packetin(&stream, &comment_header);
    ogg_stream_packetin(&stream, &codebook_header);

    // Flushing these headers now guarentees that audio data will
    // start on a new page, which apparently makes streaming easier
    while(ogg_stream_flush(&stream, &page))
    {
        outFile.Write(page.header, page.header_len);
        outFile.Write(page.body, page.body_len);
    }

    wxProgressDialog *progress = NULL;

    wxYield();
    wxStartTimer();

    int numWaveTracks;
    WaveTrack **waveTracks;
    tracks->GetWaveTracks(selectionOnly, &numWaveTracks, &waveTracks);
    Mixer *mixer = new Mixer(numWaveTracks, waveTracks,
                             tracks->GetTimeTrack(),
                             t0, t1,
                             stereo? 2: 1, SAMPLES_PER_RUN, false,
                             rate, floatSample);

    while(!cancelling && !eos) {
        float **vorbis_buffer = vorbis_analysis_buffer(&dsp, SAMPLES_PER_RUN);
        sampleCount samplesThisRun = mixer->Process(SAMPLES_PER_RUN);

        if (samplesThisRun == 0) {
            // Tell the library that we wrote 0 bytes - signalling the end.
            vorbis_analysis_wrote(&dsp, 0);
        }
        else {

            float *left = (float *)mixer->GetBuffer(0);
            memcpy(vorbis_buffer[0], left, sizeof(float)*SAMPLES_PER_RUN);

            if(stereo) {
                float *right = (float *)mixer->GetBuffer(1);
                memcpy(vorbis_buffer[1], right, sizeof(float)*SAMPLES_PER_RUN);
            }

            // tell the encoder how many samples we have
            vorbis_analysis_wrote(&dsp, samplesThisRun);
        }

        // I don't understand what this call does, so here is the comment
        // from the example, verbatim:
        //
        //    vorbis does some data preanalysis, then divvies up blocks
        //    for more involved (potentially parallel) processing. Get
        //    a single block for encoding now
        while(vorbis_analysis_blockout(&dsp, &block) == 1) {

            // analysis, assume we want to use bitrate management
            vorbis_analysis(&block, NULL);
            vorbis_bitrate_addblock(&block);

            while(vorbis_bitrate_flushpacket(&dsp, &packet)) {

                // add the packet to the bitstream
                ogg_stream_packetin(&stream, &packet);

                // From vorbis-tools-1.0/oggenc/encode.c:
                //   If we've gone over a page boundary, we can do actual output,
                //   so do so (for however many pages are available).

                while (!eos) {
                    int result = ogg_stream_pageout(&stream, &page);
                    if (!result)
                        break;

                    outFile.Write(page.header, page.header_len);
                    outFile.Write(page.body, page.body_len);

                    if (ogg_page_eos(&page))
                        eos = 1;
                }
            }
        }

        if(progress) {
            int progressvalue = int (1000 * ((mixer->MixGetCurrentTime()-t0) /
                                             (t1-t0)));
            cancelling = !progress->Update(progressvalue);
        }
        else if(wxGetElapsedTime(false) > 500) {

            wxString message = selectionOnly ?
                               _("Exporting the selected audio as Ogg Vorbis") :
                               _("Exporting the entire project as Ogg Vorbis");

            progress = new wxProgressDialog(
                _("Export"),
                message,
                1000,
                parent,
                wxPD_CAN_ABORT | wxPD_REMAINING_TIME | wxPD_AUTO_HIDE);
        }
    }

    delete mixer;

    ogg_stream_clear(&stream);

    vorbis_block_clear(&block);
    vorbis_dsp_clear(&dsp);
    vorbis_info_clear(&info);

    outFile.Close();

    if(progress)
        delete progress;

    return true;
}
bool Start(void *ctx, int iInChannels, int iInRate, int iInBits,
          const char* title, const char* artist,
          const char* albumartist, const char* album,
          const char* year, const char* track, const char* genre,
          const char* comment, int iTrackLength)
{
  ogg_context *context = (ogg_context *)ctx;
  if (!context || !context->callbacks.write)
    return false;

  // we accept only 2 ch 16bit atm
  if (iInChannels != 2 || iInBits != 16)
    return false;

  if (preset == -1)
    vorbis_encode_init(&context->vorbisInfo, iInChannels, iInRate, -1, bitrate*1000, -1);
  else
    vorbis_encode_init_vbr(&context->vorbisInfo, iInChannels, iInRate, float(preset)/10.0f);

  /* add a comment */
  vorbis_comment comm;
  vorbis_comment_init(&comm);
  vorbis_comment_add_tag(&comm, (char*)"comment", (char*)comment);
  vorbis_comment_add_tag(&comm, (char*)"artist", (char*)artist);
  vorbis_comment_add_tag(&comm, (char*)"title", (char*)title);
  vorbis_comment_add_tag(&comm, (char*)"album", (char*)album);
  vorbis_comment_add_tag(&comm, (char*)"albumartist", (char*)albumartist);
  vorbis_comment_add_tag(&comm, (char*)"genre", (char*)genre);
  vorbis_comment_add_tag(&comm, (char*)"tracknumber", (char*)track);
  vorbis_comment_add_tag(&comm, (char*)"date", (char*)year);

  /* set up the analysis state and auxiliary encoding storage */
  vorbis_analysis_init(&context->vorbisDspState, &context->vorbisInfo);

  vorbis_block_init(&context->vorbisDspState, &context->vorbisBlock);

  /* set up our packet->stream encoder */
  /* pick a random serial number; that way we can more likely build
  chained streams just by concatenation */
  srand((unsigned int)time(NULL));
  ogg_stream_init(&context->oggStreamState, rand());

  /* write out the metadata */
  ogg_packet header;
  ogg_packet header_comm;
  ogg_packet header_code;
  ogg_page   page;

  vorbis_analysis_headerout(&context->vorbisDspState, &comm,
                            &header, &header_comm, &header_code);

  ogg_stream_packetin(&context->oggStreamState, &header);
  ogg_stream_packetin(&context->oggStreamState, &header_comm);
  ogg_stream_packetin(&context->oggStreamState, &header_code);

  while (1)
  {
    /* This ensures the actual
     * audio data will start on a new page, as per spec
     */
    int result = ogg_stream_flush(&context->oggStreamState, &page);
    if (result == 0)
      break;
    context->callbacks.write(context->callbacks.opaque, page.header, page.header_len);
    context->callbacks.write(context->callbacks.opaque, page.body, page.body_len);
  }
  vorbis_comment_clear(&comm);

  context->inited = true;
  return true;
}
//________________________________________________
//   Init Vorbis encoder
// frequence    : Impose frequency , 0 means reuse the incoming fq
// mode			: VBR CBR
// bitrate for CBR	: bitrate in kbps (96,192...)
//		  for VBR	: quality (0, 1, 2, ... 11)
//				
// return 0 : init failed
//                              1 : init succeeded
//_______________________________________________
uint8_t AVDMProcessAudio_Vorbis::init( uint32_t bitrate, uint8_t mode)
{
	ogg_packet header1,header2,header3;
	int err;

 	vorbis_info_init(&VI) ;
 
	if (mode==0) {  //VBR
		err=vorbis_encode_init_vbr(&VI,
			      _wavheader->channels,
			       _wavheader->frequency,
			      ((float)bitrate-1)/10
			      );
	} else {  //CBR
		err=vorbis_encode_init(&VI,
			      _wavheader->channels,
			       _wavheader->frequency,
			      -1, // Max bitrate      
			      bitrate*1000, //long nominal_bitrate,
			      -1 //long min_bitrate))
			      );
	}
	if (err!=0) {
		printf("vorbis init error\n");
		return 0;
	}
	vorbis_analysis_init(&VD, &VI) ;
	vorbis_block_init(&VD, &VB);
      	vorbis_comment_init(&VC);
	vorbis_comment_add_tag(&VC, "encoder", "AVIDEMUX2") ;
	
	vorbis_analysis_headerout(&VD, &VC, &header1,
                                &header2, &header3);

				
	// Store all headers as extra data
	// see ogg vorbis decode for details
	// we need 3 packets
	
	_extraLen=header1.bytes+header2.bytes+header3.bytes+3*sizeof(uint32_t);
	_extraData=new uint8_t[_extraLen];
	
	uint32_t *ex=(uint32_t *)_extraData;
	uint8_t *d;
	d=_extraData+sizeof(uint32_t)*3;
	ex[0]=header1.bytes;
	ex[1]=header2.bytes;
	ex[2]=header3.bytes;
	memcpy(d,header1.packet,ex[0]);
	d+=ex[0];
	memcpy(d,header2.packet,ex[1]);
	d+=ex[1];
	memcpy(d,header3.packet,ex[2]);
	vorbis_comment_clear(&VC);
			
	printf("\nVorbis encoder initialized\n");
	if (mode==0)
		printf("VBR Quality:%i\n",bitrate-1);
	else
		printf("CBR Bitrate:%lu\n",bitrate);
	printf("Channels:%lu\n",_wavheader->channels);
	printf("Frequenc:%lu\n",_wavheader->frequency);
    return 1;
}
Exemple #25
0
static int
ogg_write_header (SF_PRIVATE *psf, int UNUSED (calc_length))
{
	OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
	VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ;
	int k, ret ;

	vorbis_info_init (&vdata->vi) ;

	/* The style of encoding should be selectable here, VBR quality mode. */
	ret = vorbis_encode_init_vbr (&vdata->vi, psf->sf.channels, psf->sf.samplerate, vdata->quality) ;

#if 0
	ret = vorbis_encode_init (&vdata->vi, psf->sf.channels, psf->sf.samplerate, -1, 128000, -1) ; /* average bitrate mode */
	ret = ( vorbis_encode_setup_managed (&vdata->vi, psf->sf.channels,
						 psf->sf.samplerate, -1, 128000, -1) ||
		vorbis_encode_ctl (&vdata->vi, OV_ECTL_RATEMANAGE_AVG, NULL) ||
		vorbis_encode_setup_init (&vdata->vi)) ;
#endif
	if (ret)
		return SFE_BAD_OPEN_FORMAT ;

	vdata->loc = 0 ;

	/* add a comment */
	vorbis_comment_init (&vdata->vc) ;

	vorbis_comment_add_tag (&vdata->vc, "ENCODER", "libsndfile") ;
	for (k = 0 ; k < SF_MAX_STRINGS ; k++)
	{	const char * name ;

		if (psf->strings [k].type == 0)
			break ;

		switch (psf->strings [k].type)
		{	case SF_STR_TITLE :			name = "TITLE" ; break ;
			case SF_STR_COPYRIGHT : 	name = "COPYRIGHT" ; break ;
			case SF_STR_SOFTWARE :		name = "SOFTWARE" ; break ;
			case SF_STR_ARTIST :		name = "ARTIST" ; break ;
			case SF_STR_COMMENT :		name = "COMMENT" ; break ;
			case SF_STR_DATE :			name = "DATE" ; break ;
			case SF_STR_ALBUM :			name = "ALBUM" ; break ;
			case SF_STR_LICENSE :		name = "LICENSE" ; break ;
			case SF_STR_TRACKNUMBER :	name = "TRACKNUMBER" ; break ;
			case SF_STR_GENRE :			name = "GENRE" ; break ;
			default : continue ;
			} ;

		vorbis_comment_add_tag (&vdata->vc, name, psf->strings [k].str) ;
		} ;

	/* set up the analysis state and auxiliary encoding storage */
	vorbis_analysis_init (&vdata->vd, &vdata->vi) ;
	vorbis_block_init (&vdata->vd, &vdata->vb) ;

	/*
	**	Set up our packet->stream encoder.
	**	Pick a random serial number ; that way we can more likely build
	**	chained streams just by concatenation.
	*/

	ogg_stream_init (&odata->os, psf_rand_int32 ()) ;

	/* Vorbis streams begin with three headers ; the initial header (with
	   most of the codec setup parameters) which is mandated by the Ogg
	   bitstream spec.  The second header holds any comment fields.	 The
	   third header holds the bitstream codebook.  We merely need to
	   make the headers, then pass them to libvorbis one at a time ;
	   libvorbis handles the additional Ogg bitstream constraints */

	{	ogg_packet header ;
		ogg_packet header_comm ;
		ogg_packet header_code ;
		int result ;

		vorbis_analysis_headerout (&vdata->vd, &vdata->vc, &header, &header_comm, &header_code) ;
		ogg_stream_packetin (&odata->os, &header) ; /* automatically placed in its own page */
		ogg_stream_packetin (&odata->os, &header_comm) ;
		ogg_stream_packetin (&odata->os, &header_code) ;

		/* This ensures the actual
		 * audio data will start on a new page, as per spec
		 */
		while ((result = ogg_stream_flush (&odata->os, &odata->og)) != 0)
		{	psf_fwrite (odata->og.header, 1, odata->og.header_len, psf) ;
			psf_fwrite (odata->og.body, 1, odata->og.body_len, psf) ;
			} ;
	}

	return 0 ;
} /* ogg_write_header */
Exemple #26
0
int main(int argc,char *argv[]){
  int c,long_option_index,ret;

  ogg_stream_state to; /* take physical pages, weld into a logical
                           stream of packets */
  ogg_stream_state vo; /* take physical pages, weld into a logical
                           stream of packets */
  ogg_page         og; /* one Ogg bitstream page.  Vorbis packets are inside */
  ogg_packet       op; /* one raw packet of data for decode */

  theora_state     td;
  theora_info      ti;
  theora_comment   tc;

  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 */

  int audioflag=0;
  int videoflag=0;
  int akbps=0;
  int vkbps=0;

  ogg_int64_t audio_bytesout=0;
  ogg_int64_t video_bytesout=0;
  double timebase;


  FILE* outfile = stdout;

#ifdef _WIN32 
# ifdef THEORA_PERF_DATA
    LARGE_INTEGER start_time;
    LARGE_INTEGER final_time;

    LONGLONG elapsed_ticks;
    LARGE_INTEGER ticks_per_second;
    
    LONGLONG elapsed_secs;
    LONGLONG elapsed_sec_mod;
    double elapsed_secs_dbl ;
# endif
  /* We need to set stdin/stdout to binary mode. Damn windows. */
  /* if we were reading/writing a file, it would also need to in
     binary mode, eg, fopen("file.wav","wb"); */
  /* Beware the evil ifdef. We avoid these where we can, but this one we
     cannot. Don't add any more, you'll probably go to hell if you do. */
  _setmode( _fileno( stdin ), _O_BINARY );
  _setmode( _fileno( stdout ), _O_BINARY );


#endif

  while((c=getopt_long(argc,argv,optstring,options,&long_option_index))!=EOF){
    switch(c){
    case 'o':
      outfile=fopen(optarg,"wb");
      if(outfile==NULL){
        fprintf(stderr,"Unable to open output file '%s'\n", optarg);
        exit(1);
      }
      break;;

    case 'a':
      audio_q=atof(optarg)*.099;
      if(audio_q<-.1 || audio_q>1){
        fprintf(stderr,"Illegal audio quality (choose -1 through 10)\n");
        exit(1);
      }
      audio_r=-1;
      break;

    case 'v':
      video_q=rint(atof(optarg)*6.3);
      if(video_q<0 || video_q>63){
        fprintf(stderr,"Illegal video quality (choose 0 through 10)\n");
        exit(1);
      }
      video_r=0;
      break;

    case 'A':
      audio_r=atof(optarg)*1000;
      if(audio_q<0){
        fprintf(stderr,"Illegal audio quality (choose > 0 please)\n");
        exit(1);
      }
      audio_q=-99;
      break;

    case 'V':
      video_r=rint(atof(optarg)*1000);
      if(video_r<45000 || video_r>2000000){
        fprintf(stderr,"Illegal video bitrate (choose 45kbps through 2000kbps)\n");
        exit(1);
      }
      video_q=0;
     break;

    case 's':
      video_an=rint(atof(optarg));
      break;

    case 'S':
      video_ad=rint(atof(optarg));
      break;

    case 'f':
      video_hzn=rint(atof(optarg));
      break;

    case 'F':
      video_hzd=rint(atof(optarg));
      break;

    default:
      usage();
    }
  }

  while(optind<argc){
    /* assume that anything following the options must be a filename */
    id_file(argv[optind]);
    optind++;
  }



#ifdef THEORA_PERF_DATA
# ifdef WIN32
    QueryPerformanceCounter(&start_time);
# endif
#endif


  /* yayness.  Set up Ogg output stream */
  srand(time(NULL));
  {
    /* need two inequal serial numbers */
    int serial1, serial2;
    serial1 = rand();
    serial2 = rand();
    if (serial1 == serial2) serial2++;
    ogg_stream_init(&to,serial1);
    ogg_stream_init(&vo,serial2);
  }

  /* Set up Theora encoder */
  if(!video){
    fprintf(stderr,"No video files submitted for compression?\n");
    exit(1);
  }
  /* Theora has a divisible-by-sixteen restriction for the encoded video size */
  /* scale the frame size up to the nearest /16 and calculate offsets */
  video_x=((frame_x + 15) >>4)<<4;
  video_y=((frame_y + 15) >>4)<<4;
  /* We force the offset to be even.
     This ensures that the chroma samples align properly with the luma
      samples. */
  frame_x_offset=((video_x-frame_x)/2)&~1;
  frame_y_offset=((video_y-frame_y)/2)&~1;

  theora_info_init(&ti);
  ti.width=video_x;
  ti.height=video_y;
  ti.frame_width=frame_x;
  ti.frame_height=frame_y;
  ti.offset_x=frame_x_offset;
  ti.offset_y=frame_y_offset;
  ti.fps_numerator=video_hzn;
  ti.fps_denominator=video_hzd;
  ti.aspect_numerator=video_an;
  ti.aspect_denominator=video_ad;
  ti.colorspace=OC_CS_UNSPECIFIED;
  ti.pixelformat=OC_PF_420;
  ti.target_bitrate=video_r;
  ti.quality=video_q;

  ti.dropframes_p=0;
  ti.quick_p=1;
  ti.keyframe_auto_p=1;
  ti.keyframe_frequency=64;
  ti.keyframe_frequency_force=64;
  ti.keyframe_data_target_bitrate=video_r*1.5;
  ti.keyframe_auto_threshold=80;
  ti.keyframe_mindistance=8;
  ti.noise_sensitivity=1;

  theora_encode_init(&td,&ti);
  theora_info_clear(&ti);

  /* initialize Vorbis too, assuming we have audio to compress. */
  if(audio){
    vorbis_info_init(&vi);
    if(audio_q>-99)
      ret = vorbis_encode_init_vbr(&vi,audio_ch,audio_hz,audio_q);
    else
      ret = vorbis_encode_init(&vi,audio_ch,audio_hz,-1,audio_r,-1);
    if(ret){
      fprintf(stderr,"The Vorbis encoder could not set up a mode according to\n"
              "the requested quality or bitrate.\n\n");
      exit(1);
    }

    vorbis_comment_init(&vc);
    vorbis_analysis_init(&vd,&vi);
    vorbis_block_init(&vd,&vb);
  }

  /* write the bitstream header packets with proper page interleave */

  /* first packet will get its own page automatically */
  theora_encode_header(&td,&op);
  ogg_stream_packetin(&to,&op);
  if(ogg_stream_pageout(&to,&og)!=1){
    fprintf(stderr,"Internal Ogg library error.\n");
    exit(1);
  }
  fwrite(og.header,1,og.header_len,outfile);
  fwrite(og.body,1,og.body_len,outfile);

  /* create the remaining theora headers */
  theora_comment_init(&tc);
  theora_encode_comment(&tc,&op);
  ogg_stream_packetin(&to,&op);
  /*theora_encode_comment() doesn't take a theora_state parameter, so it has to
     allocate its own buffer to pass back the packet data.
    If we don't free it here, we'll leak.
    libogg2 makes this much cleaner: the stream owns the buffer after you call
     packetin in libogg2, but this is not true in libogg1.*/
  free(op.packet);
  theora_encode_tables(&td,&op);
  ogg_stream_packetin(&to,&op);

  if(audio){
    ogg_packet header;
    ogg_packet header_comm;
    ogg_packet header_code;

    vorbis_analysis_headerout(&vd,&vc,&header,&header_comm,&header_code);
    ogg_stream_packetin(&vo,&header); /* automatically placed in its own
                                         page */
    if(ogg_stream_pageout(&vo,&og)!=1){
      fprintf(stderr,"Internal Ogg library error.\n");
      exit(1);
    }
    fwrite(og.header,1,og.header_len,outfile);
    fwrite(og.body,1,og.body_len,outfile);

    /* remaining vorbis header packets */
    ogg_stream_packetin(&vo,&header_comm);
    ogg_stream_packetin(&vo,&header_code);
  }

  /* Flush the rest of our headers. This ensures
     the actual data in each stream will start
     on a new page, as per spec. */
  while(1){
    int result = ogg_stream_flush(&to,&og);
      if(result<0){
        /* can't get here */
        fprintf(stderr,"Internal Ogg library error.\n");
        exit(1);
      }
    if(result==0)break;
    fwrite(og.header,1,og.header_len,outfile);
    fwrite(og.body,1,og.body_len,outfile);
  }
  if(audio){
    while(1){
      int result=ogg_stream_flush(&vo,&og);
      if(result<0){
        /* can't get here */
        fprintf(stderr,"Internal Ogg library error.\n");
        exit(1);
      }
      if(result==0)break;
      fwrite(og.header,1,og.header_len,outfile);
      fwrite(og.body,1,og.body_len,outfile);
    }
  }

  /* setup complete.  Raw processing loop */
  fprintf(stderr,"Compressing....\n");
  while(1){
    ogg_page audiopage;
    ogg_page videopage;

    /* is there an audio page flushed?  If not, fetch one if possible */
    audioflag=fetch_and_process_audio(audio,&audiopage,&vo,&vd,&vb,audioflag);

    /* is there a video page flushed?  If not, fetch one if possible */
    videoflag=fetch_and_process_video(video,&videopage,&to,&td,videoflag);

    /* no pages of either?  Must be end of stream. */
    if(!audioflag && !videoflag)break;

    /* which is earlier; the end of the audio page or the end of the
       video page? Flush the earlier to stream */
    {
      int audio_or_video=-1;
      double audiotime=
        audioflag?vorbis_granule_time(&vd,ogg_page_granulepos(&audiopage)):-1;
      double videotime=
        videoflag?theora_granule_time(&td,ogg_page_granulepos(&videopage)):-1;

      if(!audioflag){
        audio_or_video=1;
      } else if(!videoflag) {
        audio_or_video=0;
      } else {
        if(audiotime<videotime)
          audio_or_video=0;
        else
          audio_or_video=1;
      }

      if(audio_or_video==1){
        /* flush a video page */
        video_bytesout+=fwrite(videopage.header,1,videopage.header_len,outfile);
        video_bytesout+=fwrite(videopage.body,1,videopage.body_len,outfile);
        videoflag=0;
        timebase=videotime;
        
      }else{
        /* flush an audio page */
        audio_bytesout+=fwrite(audiopage.header,1,audiopage.header_len,outfile);
        audio_bytesout+=fwrite(audiopage.body,1,audiopage.body_len,outfile);
        audioflag=0;
        timebase=audiotime;
      }
      {
        int hundredths=timebase*100-(long)timebase*100;
        int seconds=(long)timebase%60;
        int minutes=((long)timebase/60)%60;
        int hours=(long)timebase/3600;
        
        if(audio_or_video)
          vkbps=rint(video_bytesout*8./timebase*.001);
        else
          akbps=rint(audio_bytesout*8./timebase*.001);
        
        fprintf(stderr,
                "\r      %d:%02d:%02d.%02d audio: %dkbps video: %dkbps                 ",
                hours,minutes,seconds,hundredths,akbps,vkbps);
      }
    }

  }

  /* clear out state */

  if(audio){
    ogg_stream_clear(&vo);
    vorbis_block_clear(&vb);
    vorbis_dsp_clear(&vd);
    vorbis_comment_clear(&vc);
    vorbis_info_clear(&vi);
  }
  if(video){
    ogg_stream_clear(&to);
    theora_clear(&td);
  }

  if(outfile && outfile!=stdout)fclose(outfile);

  fprintf(stderr,"\r   \ndone.\n\n");

#ifdef THEORA_PERF_DATA
# ifdef WIN32
    QueryPerformanceCounter(&final_time);
    elapsed_ticks = final_time.QuadPart - start_time.QuadPart;
    ticks_per_second;
    QueryPerformanceFrequency(&ticks_per_second);
    elapsed_secs = elapsed_ticks / ticks_per_second.QuadPart;
    elapsed_sec_mod = elapsed_ticks % ticks_per_second.QuadPart;
    elapsed_secs_dbl = elapsed_secs;
    elapsed_secs_dbl += ((double)elapsed_sec_mod / (double)ticks_per_second.QuadPart);
    printf("Encode time = %lld ticks\n", elapsed_ticks);
    printf("~%lld and %lld / %lld seconds\n", elapsed_secs, elapsed_sec_mod, ticks_per_second.QuadPart);
    printf("~%Lf seconds\n", elapsed_secs_dbl);
# endif

#endif 

  return(0);

}