Beispiel #1
0
void EncoderVorbis::initStream() {
    // set up analysis state and auxiliary encoding storage
    vorbis_analysis_init(&m_vdsp, &m_vinfo);
    vorbis_block_init(&m_vdsp, &m_vblock);

    // set up packet-to-stream encoder; attach a random serial number
    srand(time(0));
    ogg_stream_init(&m_oggs, getSerial());

    // add comment
    vorbis_comment_init(&m_vcomment);
    vorbis_comment_add_tag(&m_vcomment, "ENCODER", "mixxx/libvorbis");
    if (m_metaDataArtist != NULL)
        vorbis_comment_add_tag(&m_vcomment, "ARTIST", m_metaDataArtist);
    if (m_metaDataTitle != NULL)
        vorbis_comment_add_tag(&m_vcomment, "TITLE", m_metaDataTitle);
        if (m_metaDataAlbum != NULL)
        vorbis_comment_add_tag(&m_vcomment, "ALBUM", m_metaDataAlbum);

    // set up the vorbis headers
    ogg_packet headerInit;
    ogg_packet headerComment;
    ogg_packet headerCode;
    vorbis_analysis_headerout(&m_vdsp, &m_vcomment, &headerInit, &headerComment, &headerCode);
    ogg_stream_packetin(&m_oggs, &headerInit);
    ogg_stream_packetin(&m_oggs, &headerComment);
    ogg_stream_packetin(&m_oggs, &headerCode);

        //The encoder is now inialized
        // Encode method will start streaming by sending the header first
        m_header_write = true;
    m_bStreamInitialized = true;
}
Beispiel #2
0
static void add_tag(vorbis_comment *vc, oe_options *opt,char *name, char *value)
{
    char *utf8;
    if (opt->isutf8)
    {
	if (!utf8_validate(value)) {
	    fprintf(stderr, _("'%s' is not valid UTF-8, cannot add\n"), name?name:"comment");
	} else {
	    if(name == NULL) {
		vorbis_comment_add(vc, value);
            }
            else {
		vorbis_comment_add_tag(vc, name, value);
            }
	}
    }
    else if(utf8_encode(value, &utf8) >= 0)
    {
        if(name == NULL) {
            vorbis_comment_add(vc, utf8);
        }
        else {
            vorbis_comment_add_tag(vc, name, utf8);
        }
        free(utf8);
    }
    else {
        fprintf(stderr, _("Couldn't convert comment to UTF-8, cannot add\n"));
    }
}
		void OggWriter::writeHeader() {
			vorbis_comment * vc = static_cast< vorbis_comment * >( std::malloc( sizeof( vorbis_comment ) ) );
			this->comments_.reset( vc, vorbisCommentHelper );
			vorbis_comment_init( vc );
			// NOTE: dirty hack for the stupid prototype of vorbis_comment_add_tag.
			vorbis_comment_add_tag( vc, const_cast< char * >( "TITLE" ), const_cast< char * >( this->getTitle().c_str() ) );
			vorbis_comment_add_tag( vc, const_cast< char * >( "ALBUM" ), const_cast< char * >( this->getAlbum().c_str() ) );
			vorbis_comment_add_tag( vc, const_cast< char * >( "ARTIST" ), const_cast< char * >( this->getArtist().c_str() ) );

			ogg_packet header;
			ogg_packet header_common;
			ogg_packet header_code;

			vorbis_analysis_headerout( this->dsp_.get(), vc, &header, &header_common, &header_code );
			ogg_stream_packetin( this->muxer_.get(), &header );
			ogg_stream_packetin( this->muxer_.get(), &header_common );
			ogg_stream_packetin( this->muxer_.get(), &header_code );

			ogg_page og;
			for(;;) {
				int ret = ogg_stream_flush( this->muxer_.get(), &og );
				if( ret == 0 ) {
					break;
				}
				std::fwrite( og.header, 1, og.header_len, this->fout_.get() );
				std::fwrite( og.body, 1, og.body_len, this->fout_.get() );
			}
		}
Beispiel #4
0
static int ogg_write_header(AVFormatContext *avfcontext) 
{
    OggContext *context = avfcontext->priv_data;
    AVCodecContext *avccontext ;
    vorbis_info vi ;
    vorbis_dsp_state vd ;
    vorbis_comment vc ;
    vorbis_block vb ;
    ogg_packet header, header_comm, header_code ; 
    int n ;
    
    srand(time(NULL));
    ogg_stream_init(&context->os, rand());
    
    for(n = 0 ; n < avfcontext->nb_streams ; n++) {
	avccontext = &avfcontext->streams[n]->codec ;

	/* begin vorbis specific code */
		
	vorbis_info_init(&vi) ;

	/* code copied from libavcodec/oggvorbis.c */

	if(oggvorbis_init_encoder(&vi, avccontext) < 0) {
	    fprintf(stderr, "ogg_write_header: init_encoder failed") ;
	    return -1 ;
	}

	vorbis_analysis_init(&vd, &vi) ;
	vorbis_block_init(&vd, &vb) ;
	
	vorbis_comment_init(&vc) ;
	vorbis_comment_add_tag(&vc, "encoder", "ffmpeg") ;
	if(*avfcontext->title)
	    vorbis_comment_add_tag(&vc, "title", avfcontext->title) ;

	vorbis_analysis_headerout(&vd, &vc, &header,
				  &header_comm, &header_code) ;
	ogg_stream_packetin(&context->os, &header) ;
	ogg_stream_packetin(&context->os, &header_comm) ;
	ogg_stream_packetin(&context->os, &header_code) ;  
	
	vorbis_block_clear(&vb) ;
	vorbis_dsp_clear(&vd) ;
	vorbis_info_clear(&vi) ;
	vorbis_comment_clear(&vc) ;
	
	/* end of vorbis specific code */

	context->header_handled = 0 ;
	context->base_packet_no = 0 ;
    }
    
    return 0 ;
}
bool VorbisWriter::open(const QString &fn, long sr, bool s) {
	bool b = AudioFileWriter::open(fn + ".ogg", sr, s);

	if (!b)
		return false;

	int quality = preferences.get(Pref::OutputFormatVorbisQuality).toInt();

	pd = new VorbisWriterPrivateData;
	vorbis_info_init(&pd->vi);

	if (vorbis_encode_init_vbr(&pd->vi, stereo ? 2 : 1, sampleRate, (float)quality / 10.0f) != 0) {
		delete pd;
		pd = NULL;
		return false;
	}

	// TODO: the docs vaguely mention that stereo coupling can be disabled
	// with vorbis_encode_ctl(), but I didn't find anything concrete

	vorbis_comment_init(&pd->vc);
	// vorbis_comment_add_tag() in libvorbis up to version 1.2.0
	// incorrectly takes a char * instead of a const char *.  to prevent
	// compiler warnings we use const_cast<>(), since it's known that
	// libvorbis does not change the arguments.
	vorbis_comment_add_tag(&pd->vc, const_cast<char *>("COMMENT"), const_cast<char *>(tagComment.toUtf8().constData()));
	vorbis_comment_add_tag(&pd->vc, const_cast<char *>("DATE"), const_cast<char *>(tagTime.toString("yyyy-MM-dd hh:mm").toAscii().constData()));
	vorbis_comment_add_tag(&pd->vc, const_cast<char *>("GENRE"), const_cast<char *>("Speech (Skype Call)"));

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

	std::srand(std::time(NULL));
	ogg_stream_init(&pd->os, std::rand());

	ogg_packet header;
	ogg_packet header_comm;
	ogg_packet header_code;

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

	while (ogg_stream_flush(&pd->os, &pd->og) != 0) {
		file.write((const char *)pd->og.header, pd->og.header_len);
		file.write((const char *)pd->og.body, pd->og.body_len);
	}

	return true;
}
Beispiel #6
0
/*!
 * \brief Create a new OGG/Vorbis filestream and set it up for writing.
 * \param s File pointer that points to on-disk storage.
 * \param comment Comment that should be embedded in the OGG/Vorbis file.
 * \return A new filestream.
 */
static int ogg_vorbis_rewrite(struct ast_filestream *s,
						 const char *comment)
{
	ogg_packet header;
	ogg_packet header_comm;
	ogg_packet header_code;
	struct ogg_vorbis_desc *tmp = (struct ogg_vorbis_desc *) s->_private;

	tmp->writing = 1;
	tmp->writing_pcm_pos = 0;

	vorbis_info_init(&tmp->vi);

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

	vorbis_comment_init(&tmp->vc);
	vorbis_comment_add_tag(&tmp->vc, "ENCODER", "Asterisk PBX");
	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, ast_random());

	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;
		if (!fwrite(tmp->og.header, 1, tmp->og.header_len, s->f)) {
			ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno));
		}
		if (!fwrite(tmp->og.body, 1, tmp->og.body_len, s->f)) {
			ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno));
		}
		if (ogg_page_eos(&tmp->og))
			tmp->eos = 1;
	}

	return 0;
}
Beispiel #7
0
void format_set_vorbiscomment(format_plugin_t *plugin, const char *tag, const char *value) {
    if (vorbis_comment_query_count(&plugin->vc, tag) != 0) {
        /* delete key */
        /* as libvorbis hides away all the memory functions we need to copy
         * the structure comment by comment. sorry about that...
         */
        vorbis_comment vc;
        int i; /* why does vorbis_comment use int, not size_t? */
        size_t keylen = strlen(tag);

        vorbis_comment_init(&vc);
        /* copy tags */
        for (i = 0; i < plugin->vc.comments; i++) {
            if (strncasecmp(plugin->vc.user_comments[i], tag, keylen) == 0 && plugin->vc.user_comments[i][keylen] == '=')
                continue;
            vorbis_comment_add(&vc, plugin->vc.user_comments[i]);
        }
        /* move vendor */
        vc.vendor = plugin->vc.vendor;
        plugin->vc.vendor = NULL;
        vorbis_comment_clear(&plugin->vc);
        plugin->vc = vc;
    }
    vorbis_comment_add_tag(&plugin->vc, tag, value);
}
Beispiel #8
0
TargetFileOggVorbis::TargetFileOggVorbis( const DataTargetRef &dataTarget, size_t sampleRate, size_t numChannels, SampleType sampleType )
	: cinder::audio::TargetFile( sampleRate, numChannels, sampleType ), mDataTarget( dataTarget )
{
	CI_ASSERT( mDataTarget );
	mStream = mDataTarget->getStream();

	vorbis_info_init( &mVorbisInfo );

	auto status = vorbis_encode_init_vbr( &mVorbisInfo, getNumChannels(), getSampleRate(), mVorbisBaseQuality );
	if ( status ) {
		throw AudioFormatExc( string( "TargetFileOggVorbis: invalid quality setting." ) );
	}

	vorbis_comment_init( &mVorbisComment );
	vorbis_comment_add_tag( &mVorbisComment, "ENCODER", "libcinder" );

	vorbis_analysis_init( &mVorbisDspState, &mVorbisInfo );
	vorbis_block_init( &mVorbisDspState, &mVorbisBlock );

	// a constant stream serial number is used, this is okay since no streams are multiplexed
	ogg_stream_init( &mOggStream, 0 );

	ogg_packet header, headerComment, headerCodebook;

	vorbis_analysis_headerout( &mVorbisDspState, &mVorbisComment, &header, &headerComment, &headerCodebook );
	ogg_stream_packetin( &mOggStream, &header );
	ogg_stream_packetin( &mOggStream, &headerComment );
	ogg_stream_packetin( &mOggStream, &headerCodebook );

	// flush ogg page so audio data starts on a new page
	while ( ogg_stream_flush( &mOggStream, &mOggPage ) != 0 ) {
		mStream->writeData( mOggPage.header, mOggPage.header_len );
		mStream->writeData( mOggPage.body, mOggPage.body_len );
	}
}
Beispiel #9
0
int  add_comment(char *line, vorbis_comment *vc, int raw)
{
	char	*mark, *value, *utf8_value;

	/* strip any terminal newline */
	{
		int len = strlen(line);
		if (line[len-1] == '\n') line[len-1] = '\0';
	}

	/* validation: basically, we assume it's a tag
	 * if it has an '=' after one or more valid characters,
	 * as the comment spec requires. For the moment, we
	 * also restrict ourselves to 0-terminated values */

	mark = strchr(line, '=');
	if (mark == NULL) return -1;

	value = line;
	while (value < mark) {
		if(*value < 0x20 || *value > 0x7d || *value == 0x3d) return -1;
		value++;
	}

	/* split the line by turning the '=' in to a null */
	*mark = '\0';	
	value++;

    if(raw) {
        vorbis_comment_add_tag(vc, line, value);
        return 0;
    }
	/* convert the value from the native charset to UTF-8 */
    else if (utf8_encode(value, &utf8_value) >= 0) {
		
		/* append the comment and return */
		vorbis_comment_add_tag(vc, line, utf8_value);
        free(utf8_value);
		return 0;
	} else {
		fprintf(stderr, _("Couldn't convert comment to UTF8, "
			"cannot add\n"));
		return -1;
	}
}
bool ShoutVSTEncoderOGG::Initialize()
{
  bInitialized = false;

  int ret = 0; 

  pVST->Log("[ogg] vorbis_info_init()\r\n");
  vorbis_info_init(&vi);
  long sample = (long)pVST->updateSampleRate();
  pVST->Log("[ogg] Sampling rate is %d Hz\r\n",sample);

  ret = vorbis_encode_init_vbr(&vi,2,sample,pVST->GetQuality() / 10.0f); 
  if (ret) {
    pVST->Log("[ogg] Error vorbis_encode_init_vbr\r\n");
    return false;
  }

  pVST->Log("[ogg] vorbis_comment_init()\r\n");
  vorbis_comment_init(&vc);
  vorbis_comment_add_tag(&vc,"ENCODER","ShoutVST"); 

  pVST->Log("[ogg] vorbis_analysis_init()\r\n");
  vorbis_analysis_init(&vd,&vi);
  pVST->Log("[ogg] vorbis_block_init()\r\n");
  vorbis_block_init(&vd,&vb); 

  pVST->Log("[ogg] ogg_stream_init()\r\n");
  ogg_stream_init(&os,303); // totally random number

  bInitialized = true;

  {
    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);

    while(true){
      int result=ogg_stream_flush(&os,&og);
      if(result==0)break;

      SendOGGPageToICE(&og);
    }

  } 

  pVST->Log("[ogg] ogg peachy!\r\n");


  return true;
}
void VorbisWriter::open(const std::string filepath, int sampleRate, int nchannels, size_t bytesPerSample, VorbisWriterFormat f) {
  fp = fopen(filepath.c_str(), "wb+");
  if(!fp) {
    printf("ERROR: cannot open vorbis file...\n");
    fp = NULL;
    return;
  }
  
  // encode setup
  samplerate = sampleRate;
  num_channels = nchannels;
  bytes_per_sample = bytesPerSample;
  format = f;

  int r = 0;
  vorbis_info_init(&vi);
  r = vorbis_encode_init_vbr(&vi, num_channels, sampleRate, .4); // .4 = quality

  if(r != 0) {
    printf("ERROR: cannot initialize vorbis\n");
    ::exit(0);
  }

  // create comment
  vorbis_comment_init(&vc);
  vorbis_comment_add_tag(&vc, "ENCODER", "VorbisWriter");
  
  // setup analysis
  vorbis_analysis_init(&vd, &vi);
  vorbis_block_init(&vd, &vb);

  // create ogg stream
  srand((unsigned)time(NULL));
  ogg_stream_init(&os, rand());
  
  // write headers
  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(true) {
    int result = ogg_stream_flush(&os, &og);
    if(result == 0) {
      break;
    }
    fwrite(og.header, 1, og.header_len, fp);
    fwrite(og.body, 1, og.body_len, fp);
  }

  is_setup = true;
}
Beispiel #12
0
static void add_string_from_tuple (vorbis_comment * vc, const char * name,
 const Tuple * tuple, gint field)
{
    gchar * val = tuple_get_str (tuple, field, NULL);
    if (! val)
        return;

    vorbis_comment_add_tag (vc, name, val);
    str_unref (val);
}
Beispiel #13
0
static void
copy_tag_to_vorbis_comment(vorbis_comment *vc, const struct tag *tag)
{
	for (unsigned i = 0; i < tag->num_items; i++) {
		struct tag_item *item = tag->items[i];
		char *name = g_ascii_strup(tag_item_names[item->type], -1);
		vorbis_comment_add_tag(vc, name, item->value);
		g_free(name);
	}
}
Beispiel #14
0
/* This handles the headers at the backend, here we insert the header packets
 * we want for the queue.
 */
static int process_vorbis_headers (ogg_state_t *ogg_info, ogg_codec_t *codec)
{
    vorbis_codec_t *source_vorbis = codec->specific;

    if (source_vorbis->header [0] == NULL)
        return 0;

    DEBUG0 ("Adding the 3 header packets");
    ogg_stream_packetin (&source_vorbis->new_os, source_vorbis->header [0]);
    /* NOTE: we could build a separate comment packet each time */
    if (source_vorbis->rebuild_comment)
    {
        vorbis_comment vc;
        ogg_packet header;
        ice_config_t *config;

        vorbis_comment_init (&vc);
        if (ogg_info->artist)
            vorbis_comment_add_tag (&vc, "artist", ogg_info->artist);
        if (ogg_info->title)
            vorbis_comment_add_tag (&vc, "title", ogg_info->title);
        config = config_get_config();
        vorbis_comment_add_tag (&vc, "server", config->server_id);
        config_release_config();
        vorbis_commentheader_out (&vc, &header);

        ogg_stream_packetin (&source_vorbis->new_os, &header);
        vorbis_comment_clear (&vc);
        ogg_packet_clear (&header);
    }
    else
        ogg_stream_packetin (&source_vorbis->new_os, source_vorbis->header [1]);
    ogg_stream_packetin (&source_vorbis->new_os, source_vorbis->header [2]);
    source_vorbis->rebuild_comment = 0;

    ogg_info->log_metadata = 1;
    source_vorbis->get_buffer_page = get_buffer_header;
    source_vorbis->process_packet = process_vorbis_audio;
    source_vorbis->granulepos = source_vorbis->prev_window;
    source_vorbis->initial_audio_packet = 1;
    return 1;
}
Beispiel #15
0
void ogg_encoder_begin_handler(guac_audio_stream* audio) {

    /* Allocate stream state */
    ogg_encoder_state* state = (ogg_encoder_state*)
        malloc(sizeof(ogg_encoder_state));

    /* Init state */
    vorbis_info_init(&(state->info));
    vorbis_encode_init_vbr(&(state->info), audio->channels, audio->rate, 0.4);

    vorbis_analysis_init(&(state->vorbis_state), &(state->info));
    vorbis_block_init(&(state->vorbis_state), &(state->vorbis_block));

    vorbis_comment_init(&(state->comment));
    vorbis_comment_add_tag(&(state->comment), "ENCODER", "libguac");

    ogg_stream_init(&(state->ogg_state), rand());

    /* Write headers */
    {
        ogg_packet header;
        ogg_packet header_comm;
        ogg_packet header_code;

        vorbis_analysis_headerout(
                &(state->vorbis_state),
                &(state->comment),
                &header, &header_comm, &header_code);

        ogg_stream_packetin(&(state->ogg_state), &header);
        ogg_stream_packetin(&(state->ogg_state), &header_comm);
        ogg_stream_packetin(&(state->ogg_state), &header_code);

        /* For each packet */
        while (ogg_stream_flush(&(state->ogg_state), &(state->ogg_page)) != 0) {

            /* Write packet header */
            guac_audio_stream_write_encoded(audio,
                    state->ogg_page.header,
                    state->ogg_page.header_len);

            /* Write packet body */
            guac_audio_stream_write_encoded(audio,
                    state->ogg_page.body,
                    state->ogg_page.body_len);
        }

    }

    audio->data = state;

}
static int tc_vorbis_configure(TCModuleInstance *self,
                               const char *options, vob_t *vob)
{
    VorbisPrivateData *pd = NULL;
    int samplerate = (vob->mp3frequency) ? vob->mp3frequency : vob->a_rate;
    float quality = TC_CLAMP(vob->mp3quality, 0.0, 9.9) / 10.0;
    int ret, br = vob->mp3bitrate * 1000;

    TC_MODULE_SELF_CHECK(self, "configure");

    pd = self->userdata;

    if (vob->dm_bits != 16) {
        tc_log_error(MOD_NAME, "Only 16-bit samples supported");
        return TC_ERROR;
    }
 
    pd->flush_flag    = vob->encoder_flush;
    pd->end_of_stream = TC_FALSE;
    pd->channels      = vob->dm_chan;
    pd->bits          = vob->dm_bits;
    pd->packets       = 0;
    pd->frames        = 0;

    vorbis_info_init(&pd->vi);
    if (quality > ZERO_QUALITY) {
        ret = vorbis_encode_init_vbr(&pd->vi, pd->channels,
                                     samplerate, quality);
    } else {
        ret = vorbis_encode_init(&pd->vi, pd->channels, samplerate,
                                 -1, br, -1);
    }
    if (ret) {
        tc_log_error(MOD_NAME, "the Vorbis encoder could not set up a mode"
                               " according to the requested settings.");
        ret = TC_ERROR;
    } else {
        vorbis_comment_init(&pd->vc);
        vorbis_comment_add_tag(&pd->vc, "ENCODER", PACKAGE " " VERSION);
        vorbis_analysis_init(&pd->vd, &pd->vi);
        vorbis_block_init(&pd->vd, &pd->vb);

        ret = tc_ogg_new_extradata(pd);
        if (ret == TC_OK) {
            /* publish it */
            vob->ex_a_xdata = &(pd->xdata);
        }
    }
    return ret;
}
static int vorbis_init(const char *param, int *speed, int *fragsize, int *fragnr, int *channels)
{
    ogg_packet header;
    ogg_packet header_comm;
    ogg_packet header_code;
    int eos = 0;
    int ret;
    int result;

    vorbis_fd = fopen(param ? param : "vicesnd.ogg", MODE_WRITE);
    if (!vorbis_fd) {
        return 1;
    }

    if (*channels == 2) {
        stereo = 1;
    }

    vorbis_info_init(&vi);
    ret = vorbis_encode_init_vbr(&vi, *channels, *speed, 0.1f);
    if (ret) {
        vorbis_info_clear(&vi);
        return -1;
    }

    vorbis_comment_init(&vc);
    vorbis_comment_add_tag(&vc, "ENCODER", "VICE");

    vorbis_analysis_init(&vd, &vi);
    vorbis_block_init(&vd, &vb);

    srand((unsigned int)time(NULL));
    ogg_stream_init(&os, rand());

    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) {
        result = ogg_stream_flush(&os, &og);
        if (!result) {
            break;
        }
        fwrite(og.header, 1, (size_t)(og.header_len), vorbis_fd);
        fwrite(og.body, 1, (size_t)(og.body_len), vorbis_fd);
    }

    return 0;
}
Beispiel #18
0
/*
 * Vorbis beginning of stream
 */
nsresult
MediaRecorder::SetupVorbisBOS()
{
    int ret;
    nsresult rv;
    PRUint32 wr;

    if (ogg_stream_init(&aState->os, rand())) {
        PR_LOG(log, PR_LOG_NOTICE, ("Failed ogg_stream_init\n"));
        return NS_ERROR_FAILURE;
    }

    vorbis_info_init(&aState->vi);
    ret = vorbis_encode_init_vbr(
        &aState->vi, params->chan, params->rate, (float)params->qual
    );
    if (ret) {
        PR_LOG(log, PR_LOG_NOTICE, ("Failed vorbis_encode_init\n"));
        return NS_ERROR_FAILURE;
    }

    vorbis_comment_init(&aState->vc);
    vorbis_comment_add_tag(&aState->vc, "ENCODER", "rainbow");
    vorbis_analysis_init(&aState->vd, &aState->vi);
    vorbis_block_init(&aState->vd, &aState->vb);

    {
        ogg_packet header;
        ogg_packet header_comm;
        ogg_packet header_code;

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

        if (ogg_stream_pageout(&aState->os, &aState->og) != 1) {
            PR_LOG(log, PR_LOG_NOTICE, ("Internal Ogg library error\n"));
            return NS_ERROR_FAILURE;
        }

        rv = WriteData(aState->og.header, aState->og.header_len, &wr);
        rv = WriteData(aState->og.body, aState->og.body_len, &wr);
    }

    return NS_OK;
}
Beispiel #19
0
static int oggvorbis_encode_init(AVCodecContext *avccontext) {
    OggVorbisContext *context = avccontext->priv_data ;
    ogg_packet header, header_comm, header_code;
    uint8_t *p;

    vorbis_info_init(&context->vi) ;
    if(oggvorbis_init_encoder(&context->vi, avccontext) < 0) {
	av_log(avccontext, AV_LOG_ERROR, "oggvorbis_encode_init: init_encoder failed") ;
	return -1 ;
    }
    vorbis_analysis_init(&context->vd, &context->vi) ;
    vorbis_block_init(&context->vd, &context->vb) ;

    vorbis_comment_init(&context->vc);
    vorbis_comment_add_tag(&context->vc, "encoder", LIBAVCODEC_IDENT) ;

    vorbis_analysis_headerout(&context->vd, &context->vc, &header,
                                &header_comm, &header_code);
    
    avccontext->extradata_size= 3*2 + header.bytes + header_comm.bytes +  header_code.bytes;
    p= avccontext->extradata= av_mallocz(avccontext->extradata_size);
    
    *(p++) = header.bytes>>8;
    *(p++) = header.bytes&0xFF;
    memcpy(p, header.packet, header.bytes);
    p += header.bytes;
    
    *(p++) = header_comm.bytes>>8;
    *(p++) = header_comm.bytes&0xFF;
    memcpy(p, header_comm.packet, header_comm.bytes);
    p += header_comm.bytes;
    
    *(p++) = header_code.bytes>>8;
    *(p++) = header_code.bytes&0xFF;
    memcpy(p, header_code.packet, header_code.bytes);
                                
/*    vorbis_block_clear(&context->vb);
    vorbis_dsp_clear(&context->vd);
    vorbis_info_clear(&context->vi);*/
    vorbis_comment_clear(&context->vc);
       
    avccontext->frame_size = OGGVORBIS_FRAME_SIZE ;
 
    avccontext->coded_frame= avcodec_alloc_frame();
    avccontext->coded_frame->key_frame= 1;
    
    return 0 ;
}
Beispiel #20
0
static av_cold int oggvorbis_encode_init(AVCodecContext *avccontext) {
    OggVorbisContext *context = avccontext->priv_data ;
    ogg_packet header, header_comm, header_code;
    uint8_t *p;
    unsigned int offset, len;

    vorbis_info_init(&context->vi) ;
    if(oggvorbis_init_encoder(&context->vi, avccontext) < 0) {
        av_log(avccontext, AV_LOG_ERROR, "oggvorbis_encode_init: init_encoder failed") ;
        return -1 ;
    }
    vorbis_analysis_init(&context->vd, &context->vi) ;
    vorbis_block_init(&context->vd, &context->vb) ;

    vorbis_comment_init(&context->vc);
    vorbis_comment_add_tag(&context->vc, "encoder", LIBAVCODEC_IDENT) ;

    vorbis_analysis_headerout(&context->vd, &context->vc, &header,
                                &header_comm, &header_code);

    len = header.bytes + header_comm.bytes +  header_code.bytes;
    avccontext->extradata_size= 64 + len + len/255;
    p = avccontext->extradata= av_mallocz(avccontext->extradata_size);
    p[0] = 2;
    offset = 1;
    offset += av_xiphlacing(&p[offset], header.bytes);
    offset += av_xiphlacing(&p[offset], header_comm.bytes);
    memcpy(&p[offset], header.packet, header.bytes);
    offset += header.bytes;
    memcpy(&p[offset], header_comm.packet, header_comm.bytes);
    offset += header_comm.bytes;
    memcpy(&p[offset], header_code.packet, header_code.bytes);
    offset += header_code.bytes;
    avccontext->extradata_size = offset;
    avccontext->extradata= av_realloc(avccontext->extradata, avccontext->extradata_size);

/*    vorbis_block_clear(&context->vb);
    vorbis_dsp_clear(&context->vd);
    vorbis_info_clear(&context->vi);*/
    vorbis_comment_clear(&context->vc);

    avccontext->frame_size = OGGVORBIS_FRAME_SIZE ;

    avccontext->coded_frame= avcodec_alloc_frame();
    avccontext->coded_frame->key_frame= 1;

    return 0 ;
}
Beispiel #21
0
void WebMEncoder::initializeAudioEncoder() {
    /* Initialize Vorbis */
    vorbis_info_init(&vi);
    const float QUALITY = 0.4f;
    int ret2=vorbis_encode_init_vbr(&vi,audioChannels,audioSampleRate,QUALITY);
    if(ret2) {
        printf("ERROR: BAD VORBIS INIT\n");
        exit(1);
    }
    /* add a comment */
    vorbis_comment_init(&vc);
    vorbis_comment_add_tag(&vc,"SOURCE","MAME Game Audio");
    /* set up the analysis state and auxiliary encoding storage */
    vorbis_analysis_init(&vd,&vi);
    vorbis_block_init(&vd,&vb);
}
already_AddRefed<TrackMetadataBase>
VorbisTrackEncoder::GetMetadata()
{
  PROFILER_LABEL("VorbisTrackEncoder", "GetMetadata",
    js::ProfileEntry::Category::OTHER);
  {
    // Wait if encoder is not initialized.
    ReentrantMonitorAutoEnter mon(mReentrantMonitor);
    while (!mCanceled && !mInitialized) {
      mon.Wait();
    }
  }

  if (mCanceled || mEncodingComplete) {
    return nullptr;
  }

  // Vorbis codec specific data
  // http://matroska.org/technical/specs/codecid/index.html
  RefPtr<VorbisMetadata> meta = new VorbisMetadata();
  meta->mBitDepth = 32; // float for desktop
  meta->mChannels = mChannels;
  meta->mSamplingFrequency = mSamplingRate;
  ogg_packet header;
  ogg_packet header_comm;
  ogg_packet header_code;
  // Add comment
  vorbis_comment vorbisComment;
  vorbis_comment_init(&vorbisComment);
  vorbis_comment_add_tag(&vorbisComment, "ENCODER",
    NS_LITERAL_CSTRING("Mozilla VorbisTrackEncoder " MOZ_APP_UA_VERSION).get());
  vorbis_analysis_headerout(&mVorbisDsp, &vorbisComment,
                            &header,&header_comm, &header_code);
  vorbis_comment_clear(&vorbisComment);
  // number of distinct packets - 1
  meta->mData.AppendElement(2);
  // Xiph-style lacing header.bytes, header_comm.bytes
  WriteLacing(&(meta->mData), header.bytes);
  WriteLacing(&(meta->mData), header_comm.bytes);

  // Append the three packets
  meta->mData.AppendElements(header.packet, header.bytes);
  meta->mData.AppendElements(header_comm.packet, header_comm.bytes);
  meta->mData.AppendElements(header_code.packet, header_code.bytes);

  return meta.forget();
}
bool startRecording(const char *outputFile)
{
	assert(hasRecordingThread==0);

	//initialize output file
	RecordingParams *rp=(RecordingParams*)malloc(sizeof(RecordingParams));
	rp->outputFile=fopen(outputFile, "wb");
	if (rp->outputFile==NULL) {
		free(rp);
		return false;
	}

	//initialize vorbis encoder
	vorbis_info_init(&rp->vi);
	vorbis_encode_init_vbr(&rp->vi, RecordingNoOfChannels, DefaultSampleRate, .5);
	vorbis_comment_init(&rp->vc);
	vorbis_comment_add_tag(&rp->vc,(char*)"ENCODER",(char*)"QGis-mapper ogg encoder");
	vorbis_analysis_init(&rp->vd, &rp->vi);
	vorbis_block_init(&rp->vd, &rp->vb);

	//initialize ogg output stream
	srand(time(NULL));
	ogg_stream_init(&rp->os,rand());
	{
		ogg_packet header;
		ogg_packet header_comm;
		ogg_packet header_code;
		
		vorbis_analysis_headerout(&rp->vd,&rp->vc,&header,&header_comm,&header_code);
		ogg_stream_packetin(&rp->os,&header);
		ogg_stream_packetin(&rp->os,&header_comm);
		ogg_stream_packetin(&rp->os,&header_code);
		
		ogg_flushall(rp);
	}

	//initialize audio buffer
	pthread_spin_lock(&recBufferLock);
	recBuffer=sb_createBuffer();
	pthread_spin_unlock(&recBufferLock);
	
	threadRunStop=0;
	pthread_create(&recordingThread, NULL, recordingThreadFct, rp);
	hasRecordingThread=true;

	return true;
}
Beispiel #24
0
bool ExportOGG::FillComment(AudacityProject *project, vorbis_comment *comment, Tags *metadata)
{
   // Retrieve tags from project if not over-ridden
   if (metadata == NULL)
      metadata = project->GetTags();

   vorbis_comment_init(comment);

   wxString n, v;
   for (bool cont = metadata->GetFirst(n, v); cont; cont = metadata->GetNext(n, v)) {
      if (n == TAG_YEAR) {
         n = wxT("DATE");
      }
      vorbis_comment_add_tag(comment,
                             (char *) (const char *) n.mb_str(wxConvUTF8),
                             (char *) (const char *) v.mb_str(wxConvUTF8));
   }

   return true;
}
Beispiel #25
0
bool ExportOGG::FillComment(AudacityProject *project, vorbis_comment *comment, const Tags *metadata)
{
   // Retrieve tags from project if not over-ridden
   if (metadata == NULL)
      metadata = project->GetTags();

   vorbis_comment_init(comment);

   wxString n;
   for (const auto &pair : metadata->GetRange()) {
      n = pair.first;
      const auto &v = pair.second;
      if (n == TAG_YEAR) {
         n = wxT("DATE");
      }
      vorbis_comment_add_tag(comment,
                             (char *) (const char *) n.mb_str(wxConvUTF8),
                             (char *) (const char *) v.mb_str(wxConvUTF8));
   }

   return true;
}
encoder_instance encoder_create_vbr(int ch, int bitrate, float quality) {
  encoder_instance state = malloc(sizeof(struct encoder_state));
  state->data = NULL;
  state->data_len = 0;
  
  vorbis_info_init(&state->vi);
  
  if (vorbis_encode_init_vbr(&state->vi, ch, bitrate, quality) != 0) {
    free(state);
    return NULL;
  }
  
  vorbis_comment_init(&state->vc);
  vorbis_comment_add_tag(&state->vc, "ENCODER", "libvorbis.js");
  
  vorbis_analysis_init(&state->vd, &state->vi);
  vorbis_block_init(&state->vd, &state->vb);
  
  srand(time(NULL));
  ogg_stream_init(&state->os, rand());
  
  return state;
}
static void
gst_vorbis_enc_metadata_set1 (const GstTagList * list, const gchar * tag,
    gpointer vorbisenc)
{
  GstVorbisEnc *enc = GST_VORBISENC (vorbisenc);
  GList *vc_list, *l;

  vc_list = gst_tag_to_vorbis_comments (list, tag);

  for (l = vc_list; l != NULL; l = l->next) {
    const gchar *vc_string = (const gchar *) l->data;
    gchar *key = NULL, *val = NULL;

    GST_LOG_OBJECT (vorbisenc, "vorbis comment: %s", vc_string);
    if (gst_tag_parse_extended_comment (vc_string, &key, NULL, &val, TRUE)) {
      vorbis_comment_add_tag (&enc->vc, key, val);
      g_free (key);
      g_free (val);
    }
  }

  g_list_foreach (vc_list, (GFunc) g_free, NULL);
  g_list_free (vc_list);
}
Beispiel #28
0
static int
vorbis_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->vinfo) ;

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

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

	vdata->loc = 0 ;

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

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

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

		switch (psf->strings.data [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->vcomment, name, psf->strings.storage + psf->strings.data [k].offset) ;
	} ;

	/* set up the analysis state and auxiliary encoding storage */
	vorbis_analysis_init (&vdata->vdsp, &vdata->vinfo) ;
	vorbis_block_init (&vdata->vdsp, &vdata->vblock) ;

	/*
	**	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->ostream, 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->vdsp, &vdata->vcomment, &header, &header_comm, &header_code) ;
		ogg_stream_packetin (&odata->ostream, &header) ; /* automatically placed in its own page */
		ogg_stream_packetin (&odata->ostream, &header_comm) ;
		ogg_stream_packetin (&odata->ostream, &header_code) ;

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

	return 0 ;
} /* vorbis_write_header */
Beispiel #29
0
static gint vorbis_open(void)
{
    ogg_packet header;
    ogg_packet header_comm;
    ogg_packet header_code;

    vorbis_init(NULL);

    vorbis_info_init(&vi);
    vorbis_comment_init(&vc);

    if (tuple)
    {
        gchar tmpstr[32];
        gint scrint;

        add_string_from_tuple (& vc, "title", tuple, FIELD_TITLE);
        add_string_from_tuple (& vc, "artist", tuple, FIELD_ARTIST);
        add_string_from_tuple (& vc, "album", tuple, FIELD_ALBUM);
        add_string_from_tuple (& vc, "genre", tuple, FIELD_GENRE);
        add_string_from_tuple (& vc, "date", tuple, FIELD_DATE);
        add_string_from_tuple (& vc, "comment", tuple, FIELD_COMMENT);

        if ((scrint = tuple_get_int(tuple, FIELD_TRACK_NUMBER, NULL)))
        {
            g_snprintf(tmpstr, sizeof(tmpstr), "%d", scrint);
            vorbis_comment_add_tag(&vc, "tracknumber", tmpstr);
        }

        if ((scrint = tuple_get_int(tuple, FIELD_YEAR, NULL)))
        {
            g_snprintf(tmpstr, sizeof(tmpstr), "%d", scrint);
            vorbis_comment_add_tag(&vc, "year", tmpstr);
        }
    }

    if (vorbis_encode_init_vbr (& vi, input.channels, input.frequency,
     v_base_quality))
    {
        vorbis_info_clear(&vi);
        return 0;
    }

    vorbis_analysis_init(&vd, &vi);
    vorbis_block_init(&vd, &vb);

    srand(time(NULL));
    ogg_stream_init(&os, rand());

    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 (ogg_stream_flush (& os, & og))
    {
        write_output(og.header, og.header_len);
        write_output(og.body, og.body_len);
    }

    return 1;
}
Beispiel #30
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);
}