headers_generator::headers_generator(int channels, int rate, int quality) {
  CHECK(1 <= quality && quality <= 100)
    << "Quality should be in range [1, 100]: " << quality;
  
  // FSB quality is integer in range [1, 100], 
  // Vorbis quality is float in range [-0.1, 1].
  // Use linear interpolation to convert between them.
  const float vorbis_quality = ((quality - 1) + (quality - 100) * 0.1) / 99.0;

  int ret = vorbis_encode_setup_vbr(info_, channels, rate, vorbis_quality);
  CHECK(ret == 0) << "vorbis_encode_setup_vbr failed: " << ret;

  int arg = 1;
  ret = vorbis_encode_ctl(info_, OV_ECTL_COUPLING_SET, &arg);
  CHECK(ret == 0) << "vorbis_encode_ctl failed: " << ret;

  ret = vorbis_encode_setup_init(info_);
  CHECK(ret == 0) << "vorbis_encode_setup_init failed: " << ret;

  ret = vorbis_analysis_init(&dsp_state_, info_);
  CHECK(ret == 0) << "vorbis_analysis_init failed: " << ret;

  ret = vorbis_analysis_headerout(
    &dsp_state_, comment_,
    &header_id_, &header_comment_, &header_setup_);
  CHECK(ret == 0) << "vorbis_analysis_headerout failed:" << ret;
}
Beispiel #2
0
static int oggvorbis_init_encoder(vorbis_info *vi, AVCodecContext *avccontext) {
    double cfreq;

    if(avccontext->flags & CODEC_FLAG_QSCALE) {
        /* variable bitrate */
        if(vorbis_encode_setup_vbr(vi, avccontext->channels,
                avccontext->sample_rate,
                avccontext->global_quality / (float)FF_QP2LAMBDA))
            return -1;
    } else {
        /* constant bitrate */
        if(vorbis_encode_setup_managed(vi, avccontext->channels,
                avccontext->sample_rate, -1, avccontext->bit_rate, -1))
            return -1;

#ifdef OGGVORBIS_VBR_BY_ESTIMATE
        /* variable bitrate by estimate */
        if(vorbis_encode_ctl(vi, OV_ECTL_RATEMANAGE_AVG, NULL))
            return -1;
#endif
    }

    /* cutoff frequency */
    if(avccontext->cutoff > 0) {
        cfreq = avccontext->cutoff / 1000.0;
        if(vorbis_encode_ctl(vi, OV_ECTL_LOWPASS_SET, &cfreq))
            return -1;
    }

    return vorbis_encode_setup_init(vi);
}
Beispiel #3
0
static av_cold int oggvorbis_init_encoder(vorbis_info *vi, AVCodecContext *avccontext) {
    double cfreq;

    if(avccontext->flags & CODEC_FLAG_QSCALE) {
        /* variable bitrate */
        if(vorbis_encode_setup_vbr(vi, avccontext->channels,
                avccontext->sample_rate,
                avccontext->global_quality / (float)FF_QP2LAMBDA / 10.0))
            return -1;
    } else {
        int minrate = avccontext->rc_min_rate > 0 ? avccontext->rc_min_rate : -1;
        int maxrate = avccontext->rc_min_rate > 0 ? avccontext->rc_max_rate : -1;

        /* constant bitrate */
        if(vorbis_encode_setup_managed(vi, avccontext->channels,
                avccontext->sample_rate, minrate, avccontext->bit_rate, maxrate))
            return -1;

        /* variable bitrate by estimate, disable slow rate management */
        if(minrate == -1 && maxrate == -1)
            if(vorbis_encode_ctl(vi, OV_ECTL_RATEMANAGE2_SET, NULL))
                return -1;
    }

    /* cutoff frequency */
    if(avccontext->cutoff > 0) {
        cfreq = avccontext->cutoff / 1000.0;
        if(vorbis_encode_ctl(vi, OV_ECTL_LOWPASS_SET, &cfreq))
            return -1;
    }

    return vorbis_encode_setup_init(vi);
}
int vorbis_encode_init_vbr(vorbis_info *vi,
			   long channels,
			   long rate,
			   
			   float base_quality /* 0. to 1. */
			   ){
  int ret=0;

  ret=vorbis_encode_setup_vbr(vi,channels,rate,base_quality);
  
  if(ret){
    vorbis_info_clear(vi);
    return ret; 
  }
  ret=vorbis_encode_setup_init(vi);
  if(ret)
    vorbis_info_clear(vi);
  return(ret);
}
Beispiel #5
0
static GstBuffer *
_create_codebook_header_buffer (void)
{
  GstBuffer *buffer;
  ogg_packet header;
  ogg_packet header_comm;
  ogg_packet header_code;

  vorbis_info_init (&vi);
  vorbis_encode_setup_vbr (&vi, 1, 44000, 0.5);
  vorbis_encode_setup_init (&vi);
  vorbis_analysis_init (&vd, &vi);
  vorbis_block_init (&vd, &vb);
  vorbis_comment_init (&vc);
  vorbis_analysis_headerout (&vd, &vc, &header, &header_comm, &header_code);

  buffer = gst_buffer_new_and_alloc (header_code.bytes);
  gst_buffer_fill (buffer, 0, header_code.packet, header_code.bytes);

  return buffer;
}
Beispiel #6
0
/*****************************************************************************
 * OpenEncoder: probe the encoder and return score
 *****************************************************************************/
static int OpenEncoder( vlc_object_t *p_this )
{
    encoder_t *p_enc = (encoder_t *)p_this;
    encoder_sys_t *p_sys;
    int i_quality, i_min_bitrate, i_max_bitrate;
    ogg_packet header[3];

    if( p_enc->fmt_out.i_codec != VLC_CODEC_VORBIS &&
            !p_enc->b_force )
    {
        return VLC_EGENERIC;
    }

    /* Allocate the memory needed to store the decoder's structure */
    if( ( p_sys = (encoder_sys_t *)malloc(sizeof(encoder_sys_t)) ) == NULL )
        return VLC_ENOMEM;
    p_enc->p_sys = p_sys;

    p_enc->pf_encode_audio = Encode;
    p_enc->fmt_in.i_codec  = VLC_CODEC_FL32;
    p_enc->fmt_out.i_codec = VLC_CODEC_VORBIS;

    config_ChainParse( p_enc, ENC_CFG_PREFIX, ppsz_enc_options, p_enc->p_cfg );

    i_quality = var_GetInteger( p_enc, ENC_CFG_PREFIX "quality" );
    if( i_quality > 10 ) i_quality = 10;
    if( i_quality < 0 ) i_quality = 0;

    if( var_GetBool( p_enc, ENC_CFG_PREFIX "cbr" ) ) i_quality = 0;
    i_max_bitrate = var_GetInteger( p_enc, ENC_CFG_PREFIX "max-bitrate" );
    i_min_bitrate = var_GetInteger( p_enc, ENC_CFG_PREFIX "min-bitrate" );

    /* Initialize vorbis encoder */
    vorbis_info_init( &p_sys->vi );

    if( i_quality > 0 )
    {
        /* VBR mode */
        if( vorbis_encode_setup_vbr( &p_sys->vi,
                                     p_enc->fmt_in.audio.i_channels, p_enc->fmt_in.audio.i_rate,
                                     i_quality * 0.1 ) )
        {
            vorbis_info_clear( &p_sys->vi );
            free( p_enc->p_sys );
            msg_Err( p_enc, "VBR mode initialisation failed" );
            return VLC_EGENERIC;
        }

        /* Do we have optional hard quality restrictions? */
        if( i_max_bitrate > 0 || i_min_bitrate > 0 )
        {
            struct ovectl_ratemanage_arg ai;
            vorbis_encode_ctl( &p_sys->vi, OV_ECTL_RATEMANAGE_GET, &ai );

            ai.bitrate_hard_min = i_min_bitrate;
            ai.bitrate_hard_max = i_max_bitrate;
            ai.management_active = 1;

            vorbis_encode_ctl( &p_sys->vi, OV_ECTL_RATEMANAGE_SET, &ai );

        }
        else
        {
            /* Turn off management entirely */
            vorbis_encode_ctl( &p_sys->vi, OV_ECTL_RATEMANAGE_SET, NULL );
        }
    }
    else
    {
        if( vorbis_encode_setup_managed( &p_sys->vi,
                                         p_enc->fmt_in.audio.i_channels, p_enc->fmt_in.audio.i_rate,
                                         i_min_bitrate > 0 ? i_min_bitrate * 1000: -1,
                                         p_enc->fmt_out.i_bitrate,
                                         i_max_bitrate > 0 ? i_max_bitrate * 1000: -1 ) )
        {
            vorbis_info_clear( &p_sys->vi );
            msg_Err( p_enc, "CBR mode initialisation failed" );
            free( p_enc->p_sys );
            return VLC_EGENERIC;
        }
    }

    vorbis_encode_setup_init( &p_sys->vi );

    /* Add a comment */
    vorbis_comment_init( &p_sys->vc);
    vorbis_comment_add_tag( &p_sys->vc, "ENCODER", "VLC media player");

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

    /* Create and store headers */
    vorbis_analysis_headerout( &p_sys->vd, &p_sys->vc,
                               &header[0], &header[1], &header[2]);
    for( int i = 0; i < 3; i++ )
    {
        if( xiph_AppendHeaders( &p_enc->fmt_out.i_extra, &p_enc->fmt_out.p_extra,
                                header[i].bytes, header[i].packet ) )
        {
            p_enc->fmt_out.i_extra = 0;
            p_enc->fmt_out.p_extra = NULL;
        }
    }

    p_sys->i_channels = p_enc->fmt_in.audio.i_channels;
    p_sys->i_last_block_size = 0;
    p_sys->i_samples_delay = 0;

    ConfigureChannelOrder(p_sys->pi_chan_table, p_sys->vi.channels,
                          p_enc->fmt_in.audio.i_physical_channels, true);

    return VLC_SUCCESS;
}
static gboolean
gst_vorbis_enc_setup (GstVorbisEnc * vorbisenc)
{

  GST_LOG_OBJECT (vorbisenc, "setup");

  if (vorbisenc->bitrate < 0 && vorbisenc->min_bitrate < 0
      && vorbisenc->max_bitrate < 0) {
    vorbisenc->quality_set = TRUE;
  }

  update_start_message (vorbisenc);

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

  if (vorbisenc->quality_set) {
    if (vorbis_encode_setup_vbr (&vorbisenc->vi,
            vorbisenc->channels, vorbisenc->frequency,
            vorbisenc->quality) != 0) {
      GST_ERROR_OBJECT (vorbisenc,
          "vorbisenc: initialisation failed: invalid parameters for quality");
      vorbis_info_clear (&vorbisenc->vi);
      return FALSE;
    }

    /* do we have optional hard quality restrictions? */
    if (vorbisenc->max_bitrate > 0 || vorbisenc->min_bitrate > 0) {
      struct ovectl_ratemanage_arg ai;

      vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_GET, &ai);

      ai.bitrate_hard_min = vorbisenc->min_bitrate;
      ai.bitrate_hard_max = vorbisenc->max_bitrate;
      ai.management_active = 1;

      vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_SET, &ai);
    }
  } else {
    long min_bitrate, max_bitrate;

    min_bitrate = vorbisenc->min_bitrate > 0 ? vorbisenc->min_bitrate : -1;
    max_bitrate = vorbisenc->max_bitrate > 0 ? vorbisenc->max_bitrate : -1;

    if (vorbis_encode_setup_managed (&vorbisenc->vi,
            vorbisenc->channels,
            vorbisenc->frequency,
            max_bitrate, vorbisenc->bitrate, min_bitrate) != 0) {
      GST_ERROR_OBJECT (vorbisenc,
          "vorbis_encode_setup_managed "
          "(c %d, rate %d, max br %ld, br %d, min br %ld) failed",
          vorbisenc->channels, vorbisenc->frequency, max_bitrate,
          vorbisenc->bitrate, min_bitrate);
      vorbis_info_clear (&vorbisenc->vi);
      return FALSE;
    }
  }

  if (vorbisenc->managed && vorbisenc->bitrate < 0) {
    vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_AVG, NULL);
  } else if (!vorbisenc->managed) {
    /* Turn off management entirely (if it was turned on). */
    vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_SET, NULL);
  }
  vorbis_encode_setup_init (&vorbisenc->vi);

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

  /* samples == granulepos start at 0 again */
  vorbisenc->samples_out = 0;

  /* fresh encoder available */
  vorbisenc->setup = TRUE;

  return TRUE;
}
Beispiel #8
0
int encvorbisInit( hb_work_object_t * w, hb_job_t * job )
{
    hb_audio_t * audio = w->audio;
    int i;
    ogg_packet header[3];

    hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) );
    w->private_data = pv;
    pv->out_discrete_channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown);

    pv->job   = job;

    hb_log( "encvorbis: opening libvorbis" );

    /* init */
    for( i = 0; i < 3; i++ )
    {
        // Zero vorbis headers so that we don't crash in mk_laceXiph
        // when vorbis_encode_setup_managed fails.
        memset( w->config->vorbis.headers[i], 0, sizeof( ogg_packet ) );
    }
    vorbis_info_init( &pv->vi );

    if( audio->config.out.bitrate > 0 )
    {
        /* 28kbps/channel seems to be the minimum for 6ch vorbis. */
        int min_bitrate = 28 * pv->out_discrete_channels;
        if (pv->out_discrete_channels > 2 && audio->config.out.bitrate < min_bitrate)
        {
            hb_log( "encvorbis: Selected bitrate (%d kbps) too low for %d channel audio.", audio->config.out.bitrate, pv->out_discrete_channels);
            hb_log( "encvorbis: Resetting bitrate to %d kbps", min_bitrate);
            /* Naughty! We shouldn't modify the audio from here. */
            audio->config.out.bitrate = min_bitrate;
        }

        if( vorbis_encode_setup_managed( &pv->vi, pv->out_discrete_channels,
              audio->config.out.samplerate, -1, 1000 * audio->config.out.bitrate, -1 ) )
        {
            hb_error( "encvorbis: vorbis_encode_setup_managed failed.\n" );
            *job->die = 1;
            return -1;
        }
    }
    else if( audio->config.out.quality != -1 )
    {
        // map VBR quality to Vorbis API (divide by 10)
        if( vorbis_encode_setup_vbr( &pv->vi, pv->out_discrete_channels,
              audio->config.out.samplerate, audio->config.out.quality/10 ) )
        {
            hb_error( "encvorbis: vorbis_encode_setup_vbr failed.\n" );
            *job->die = 1;
            return -1;
        }
    }

    if( vorbis_encode_ctl( &pv->vi, OV_ECTL_RATEMANAGE2_SET, NULL ) ||
          vorbis_encode_setup_init( &pv->vi ) )
    {
        hb_error( "encvorbis: vorbis_encode_ctl( ratemanage2_set ) OR vorbis_encode_setup_init failed.\n" );
        *job->die = 1;
        return -1;
    }

    /* add a comment */
    vorbis_comment_init( &pv->vc );
    vorbis_comment_add_tag( &pv->vc, "Encoder", "HandBrake");
    vorbis_comment_add_tag( &pv->vc, "LANGUAGE", w->config->vorbis.language);

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

    /* get the 3 headers */
    vorbis_analysis_headerout( &pv->vd, &pv->vc,
                               &header[0], &header[1], &header[2] );
    for( i = 0; i < 3; i++ )
    {
        memcpy( w->config->vorbis.headers[i], &header[i],
                sizeof( ogg_packet ) );
        memcpy( w->config->vorbis.headers[i] + sizeof( ogg_packet ),
                header[i].packet, header[i].bytes );
    }

    pv->input_samples = pv->out_discrete_channels * OGGVORBIS_FRAME_SIZE;
    audio->config.out.samples_per_frame = OGGVORBIS_FRAME_SIZE;
    pv->buf = malloc( pv->input_samples * sizeof( float ) );

    pv->list = hb_list_init();

    switch (pv->out_discrete_channels) {
        case 1:
            pv->channel_map[0] = 0;
            break;
        case 6:
            // Vorbis uses the following channel map = L C R Ls Rs Lfe
            if( audio->config.in.channel_map == &hb_ac3_chan_map )
            {
                pv->channel_map[0] = 1;
                pv->channel_map[1] = 2;
                pv->channel_map[2] = 3;
                pv->channel_map[3] = 4;
                pv->channel_map[4] = 5;
                pv->channel_map[5] = 0;
            }
            else if( audio->config.in.channel_map == &hb_smpte_chan_map )
            {
                pv->channel_map[0] = 0;
                pv->channel_map[1] = 2;
                pv->channel_map[2] = 1;
                pv->channel_map[3] = 4;
                pv->channel_map[4] = 5;
                pv->channel_map[5] = 3;
            }
            else // &hb_qt_chan_map
            {
                pv->channel_map[0] = 1;
                pv->channel_map[1] = 0;
                pv->channel_map[2] = 2;
                pv->channel_map[3] = 3;
                pv->channel_map[4] = 4;
                pv->channel_map[5] = 5;
            }
            break;
        default:
            hb_log("encvorbis.c: Unable to correctly proccess %d channels, assuming stereo.", pv->out_discrete_channels);
        case 2:
            // Assume stereo
            pv->channel_map[0] = 0;
            pv->channel_map[1] = 1;
            break;
    }

    return 0;
}
Beispiel #9
0
void CompressionTool::encodeRaw(const char *rawData, int length, int samplerate, const char *outname, AudioFormat compmode) {

	print(" - len=%ld, ch=%d, rate=%d, %dbits", length, (rawAudioType.isStereo ? 2 : 1), samplerate, rawAudioType.bitsPerSample);

#ifdef USE_VORBIS
	if (compmode == AUDIO_VORBIS) {
		char outputString[256] = "";
		int numChannels = (rawAudioType.isStereo ? 2 : 1);
		int totalSamples = length / ((rawAudioType.bitsPerSample / 8) * numChannels);
		int samplesLeft = totalSamples;
		int eos = 0;
		int totalBytes = 0;

		vorbis_info vi;
		vorbis_comment vc;
		vorbis_dsp_state vd;
		vorbis_block vb;

		ogg_stream_state os;
		ogg_page og;
		ogg_packet op;

		ogg_packet header;
		ogg_packet header_comm;
		ogg_packet header_code;

		Common::File outputOgg(outname, "wb");

		vorbis_info_init(&vi);

		if (oggparms.nominalBitr > 0) {
			int result = 0;

			/* Input is in kbps, function takes bps */
			result = vorbis_encode_setup_managed(&vi, numChannels, samplerate, (oggparms.maxBitr > 0 ? 1000 * oggparms.maxBitr : -1), (1000 * oggparms.nominalBitr), (oggparms.minBitr > 0 ? 1000 * oggparms.minBitr : -1));

			if (result == OV_EFAULT) {
				vorbis_info_clear(&vi);
				error("Error: Internal Logic Fault");
			} else if ((result == OV_EINVAL) || (result == OV_EIMPL)) {
				vorbis_info_clear(&vi);
				error("Error: Invalid bitrate parameters");
			}

			if (!oggparms.silent) {
				sprintf(outputString, "Encoding to\n         \"%s\"\nat average bitrate %i kbps (", outname, oggparms.nominalBitr);

				if (oggparms.minBitr > 0) {
					sprintf(outputString + strlen(outputString), "min %i kbps, ", oggparms.minBitr);
				} else {
					sprintf(outputString + strlen(outputString), "no min, ");
				}

				if (oggparms.maxBitr > 0) {
					sprintf(outputString + strlen(outputString), "max %i kbps),\nusing full bitrate management engine\nSet optional hard quality restrictions\n", oggparms.maxBitr);
				} else {
					sprintf(outputString + strlen(outputString), "no max),\nusing full bitrate management engine\nSet optional hard quality restrictions\n");
				}
			}
		} else {
			int result = 0;

			/* Quality input is -1 - 10, function takes -0.1 through 1.0 */
			result = vorbis_encode_setup_vbr(&vi, numChannels, samplerate, oggparms.quality * 0.1f);

			if (result == OV_EFAULT) {
				vorbis_info_clear(&vi);
				error("Internal Logic Fault");
			} else if ((result == OV_EINVAL) || (result == OV_EIMPL)) {
				vorbis_info_clear(&vi);
				error("Invalid bitrate parameters");
			}

			if (!oggparms.silent) {
				sprintf(outputString, "Encoding to\n         \"%s\"\nat quality %2.2f", outname, oggparms.quality);
			}

			if ((oggparms.minBitr > 0) || (oggparms.maxBitr > 0)) {
				struct ovectl_ratemanage_arg extraParam;
				vorbis_encode_ctl(&vi, OV_ECTL_RATEMANAGE_GET, &extraParam);

				extraParam.bitrate_hard_min = (oggparms.minBitr > 0 ? (1000 * oggparms.minBitr) : -1);
				extraParam.bitrate_hard_max = (oggparms.maxBitr > 0 ? (1000 * oggparms.maxBitr) : -1);
				extraParam.management_active = 1;

				vorbis_encode_ctl(&vi, OV_ECTL_RATEMANAGE_SET, &extraParam);

				if (!oggparms.silent) {
					sprintf(outputString + strlen(outputString), " using constrained VBR (");

					if (oggparms.minBitr != -1) {
						sprintf(outputString + strlen(outputString), "min %i kbps, ", oggparms.minBitr);
					} else {
						sprintf(outputString + strlen(outputString), "no min, ");
					}

					if (oggparms.maxBitr != -1) {
						sprintf(outputString + strlen(outputString), "max %i kbps)\nSet optional hard quality restrictions\n", oggparms.maxBitr);
					} else {
						sprintf(outputString + strlen(outputString), "no max)\nSet optional hard quality restrictions\n");
					}
				}
			} else {
				sprintf(outputString + strlen(outputString), "\n");
			}
		}

		puts(outputString);

		vorbis_encode_setup_init(&vi);
		vorbis_comment_init(&vc);
		vorbis_analysis_init(&vd, &vi);
		vorbis_block_init(&vd, &vb);
		ogg_stream_init(&os, 0);
		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;
			}

			outputOgg.write(og.header, og.header_len);
			outputOgg.write(og.body, og.body_len);
		}

		while (!eos) {
			int numSamples = ((samplesLeft < 2048) ? samplesLeft : 2048);
			float **buffer = vorbis_analysis_buffer(&vd, numSamples);

			/* We must tell the encoder that we have reached the end of the stream */
			if (numSamples == 0) {
				vorbis_analysis_wrote(&vd, 0);
			} else {
				/* Adapted from oggenc 1.1.1 */
				if (rawAudioType.bitsPerSample == 8) {
					const byte *rawDataUnsigned = (const byte *)rawData;
					for (int i = 0; i < numSamples; i++) {
						for (int j = 0; j < numChannels; j++) {
							buffer[j][i] = ((int)(rawDataUnsigned[i * numChannels + j]) - 128) / 128.0f;
						}
					}
				} else if (rawAudioType.bitsPerSample == 16) {
					if (rawAudioType.isLittleEndian) {
						for (int i = 0; i < numSamples; i++) {
							for (int j = 0; j < numChannels; j++) {
								buffer[j][i] = ((rawData[(i * 2 * numChannels) + (2 * j) + 1] << 8) | (rawData[(i * 2 * numChannels) + (2 * j)] & 0xff)) / 32768.0f;
							}
						}
					} else {
						for (int i = 0; i < numSamples; i++) {
							for (int j = 0; j < numChannels; j++) {
								buffer[j][i] = ((rawData[(i * 2 * numChannels) + (2 * j)] << 8) | (rawData[(i * 2 * numChannels) + (2 * j) + 1] & 0xff)) / 32768.0f;
							}
						}
					}
				}

				vorbis_analysis_wrote(&vd, numSamples);
			}

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

						totalBytes += outputOgg.write(og.header, og.header_len);
						totalBytes += outputOgg.write(og.body, og.body_len);

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

			rawData += 2048 * (rawAudioType.bitsPerSample / 8) * numChannels;
			samplesLeft -= 2048;
		}

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

		if (!oggparms.silent) {
			print("\nDone encoding file \"%s\"", outname);
			print("\n\tFile length:  %dm %ds", (int)(totalSamples / samplerate / 60), (totalSamples / samplerate % 60));
			print("\tAverage bitrate: %.1f kb/s\n", (8.0 * (double)totalBytes / 1000.0) / ((double)totalSamples / (double)samplerate));
		}
	}
#endif

#ifdef USE_FLAC
	if (compmode == AUDIO_FLAC) {
		int i;
		int numChannels = (rawAudioType.isStereo ? 2 : 1);
		int samplesPerChannel = length / ((rawAudioType.bitsPerSample / 8) * numChannels);
		FLAC__StreamEncoder *encoder;
		FLAC__StreamEncoderInitStatus initStatus;
		FLAC__int32 *flacData;

		flacData = (FLAC__int32 *)malloc(samplesPerChannel * numChannels * sizeof(FLAC__int32));

		if (rawAudioType.bitsPerSample == 8) {
			for (i = 0; i < samplesPerChannel * numChannels; i++) {
				FLAC__uint8 *rawDataUnsigned;
				rawDataUnsigned = (FLAC__uint8 *)rawData;
				flacData[i] = (FLAC__int32)rawDataUnsigned[i] - 0x80;
			}
		} else if (rawAudioType.bitsPerSample == 16) {
			/* The rawData pointer is an 8-bit char so we must create a new pointer to access 16-bit samples */
			FLAC__int16 *rawData16;
			rawData16 = (FLAC__int16 *)rawData;
			for (i = 0; i < samplesPerChannel * numChannels; i++) {
				flacData[i] = (FLAC__int32)rawData16[i];
			}
		}

		if (!flacparms.silent) {
			print("Encoding to\n         \"%s\"\nat compression level %d using blocksize %d\n", outname, flacparms.compressionLevel, flacparms.blocksize);
		}

		encoder = FLAC__stream_encoder_new();

		FLAC__stream_encoder_set_bits_per_sample(encoder, rawAudioType.bitsPerSample);
		FLAC__stream_encoder_set_blocksize(encoder, flacparms.blocksize);
		FLAC__stream_encoder_set_channels(encoder, numChannels);
		FLAC__stream_encoder_set_compression_level(encoder, flacparms.compressionLevel);
		FLAC__stream_encoder_set_sample_rate(encoder, samplerate);
		FLAC__stream_encoder_set_streamable_subset(encoder, false);
		FLAC__stream_encoder_set_total_samples_estimate(encoder, samplesPerChannel);
		FLAC__stream_encoder_set_verify(encoder, flacparms.verify);

		initStatus = FLAC__stream_encoder_init_file(encoder, outname, NULL, NULL);

		if (initStatus != FLAC__STREAM_ENCODER_INIT_STATUS_OK) {
			char buf[2048];
			sprintf(buf, "Error in FLAC encoder. (check the parameters)\nExact error was:%s", FLAC__StreamEncoderInitStatusString[initStatus]);
			free(flacData);
			throw ToolException(buf);
		} else {
			FLAC__stream_encoder_process_interleaved(encoder, flacData, samplesPerChannel);
		}

		FLAC__stream_encoder_finish(encoder);
		FLAC__stream_encoder_delete(encoder);

		free(flacData);

		if (!flacparms.silent) {
			print("\nDone encoding file \"%s\"", outname);
			print("\n\tFile length:  %dm %ds\n", (int)(samplesPerChannel / samplerate / 60), (samplesPerChannel / samplerate % 60));
		}
	}
#endif
}
Beispiel #10
0
static int encode_ogg (cdrom_drive *drive, rip_opts_s *rip_opts,
		       text_tag_s *text_tag, int track,
		       int tracktot, char *filename, char **filenames)
{
  ogg_stream_state os;
  ogg_page og;
  ogg_packet op;

  vorbis_dsp_state vd;
  vorbis_block vb;
  vorbis_info vi;

  long samplesdone = 0;
  int sector = 0, last_sector = 0;
  long bytes_written = 0, packetsdone = 0;
  double time_elapsed = 0.0;
  int ret = 0;
  time_t *timer;
  double time;
  
  int serialno = rand ();
  vorbis_comment vc;
  long total_samples_per_channel = 0;
  int channels = 2;
  int eos = 0;
  long rate = 44100;
  FILE *out = fopen (filename, "w+");

  timer = timer_start ();

  if (!rip_opts->managed && (rip_opts->min_bitrate > 0 || rip_opts->max_bitrate > 0)) {
    log_msg ("Min or max bitrate requires managed", FL, FN, LN);
    return -1;
  }

  if (rip_opts->bitrate < 0 && rip_opts->min_bitrate < 0 && rip_opts->max_bitrate < 0) {
    rip_opts->quality_set = 1;
  }
  
  start_func (filename, rip_opts->bitrate, rip_opts->quality, rip_opts->quality_set,
	      rip_opts->managed, rip_opts->min_bitrate, rip_opts->max_bitrate);
  
  vorbis_info_init (&vi);

  if (rip_opts->quality_set > 0) {
    if (vorbis_encode_setup_vbr (&vi, channels, rate, rip_opts->quality)) {
      log_msg ("Couldn't initialize vorbis_info", FL, FN, LN);
      vorbis_info_clear (&vi);
      return -1;
    }
    /* two options here, max or min bitrate */
    if (rip_opts->max_bitrate > 0 || rip_opts->min_bitrate > 0) {
      struct ovectl_ratemanage_arg ai;
      vorbis_encode_ctl (&vi, OV_ECTL_RATEMANAGE_GET, &ai);
      ai.bitrate_hard_min = rip_opts->min_bitrate;
      ai.bitrate_hard_max = rip_opts->max_bitrate;
      ai.management_active = 1;
      vorbis_encode_ctl (&vi, OV_ECTL_RATEMANAGE_SET, &ai);
    }
  } else {
    if (vorbis_encode_setup_managed (&vi, channels, rate,
				     rip_opts->max_bitrate > 0 ? rip_opts->max_bitrate * 1000 : -1,
				     rip_opts->bitrate * 1000,
				     rip_opts->min_bitrate > 0 ? rip_opts->min_bitrate * 1000 : -1)) {
      log_msg ("Mode init failed, encode setup managed", FL, FN, LN);
      vorbis_info_clear (&vi);
      return -1;
    }
  }

  if (rip_opts->managed && rip_opts->bitrate < 0) {
    vorbis_encode_ctl (&vi, OV_ECTL_RATEMANAGE_AVG, NULL);
  } else if (!rip_opts->managed) {
    vorbis_encode_ctl (&vi, OV_ECTL_RATEMANAGE_SET, NULL);
  }

  /* set advanced encoder options */

  vorbis_encode_setup_init (&vi);

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

  ogg_stream_init (&os, serialno);

  {
    ogg_packet header_main;
    ogg_packet header_comments;
    ogg_packet header_codebooks;
    int result;
    char buf[32];

    vorbis_comment_init (&vc);
    vorbis_comment_add_tag (&vc, "title", text_tag->songname);
    vorbis_comment_add_tag (&vc, "artist", text_tag->artistname);
    vorbis_comment_add_tag (&vc, "album", text_tag->albumname);
    vorbis_comment_add_tag (&vc, "genre", text_tag->genre);
    snprintf (buf, 32, "%d", text_tag->year);
    vorbis_comment_add_tag (&vc, "date", buf);
    snprintf (buf, 32, "%02d", text_tag->track);
    vorbis_comment_add_tag (&vc, "tracknumber", buf);
	
    vorbis_analysis_headerout (&vd, &vc, &header_main, &header_comments, &header_codebooks);

    ogg_stream_packetin (&os, &header_main);
    ogg_stream_packetin (&os, &header_comments);
    ogg_stream_packetin (&os, &header_codebooks);

    while ((result = ogg_stream_flush (&os, &og))) {
      if (result == 0)
	break;
      ret = write_page (&og, out);
      if (ret != og.header_len + og.body_len) {
	log_msg ("Failed writing data to output stream", FL, FN, LN);
	ret = -1;
      }
    }
	  
    sector = cdda_track_firstsector (drive, track);
    last_sector = cdda_track_lastsector (drive, track);
    total_samples_per_channel = (last_sector - sector) * (CD_FRAMESAMPLES / 2);
    int eos = 0;
	
    while (!eos) {
      signed char *buffer = (signed char *)malloc (CD_FRAMESIZE_RAW * READ_SECTORS);
      //use this variable as a s**t
      long sectors_read = last_sector - sector;
      if (sectors_read > READ_SECTORS)
	sectors_read = READ_SECTORS;

      sectors_read = cdda_read (drive, (signed char *)buffer, sector, sectors_read);
      int i;
	  
      if (sectors_read == 0) {
	vorbis_analysis_wrote (&vd, 0);
      } else {
	float **vorbbuf = vorbis_analysis_buffer (&vd, CD_FRAMESIZE_RAW * sectors_read);
	for (i = 0; i < (CD_FRAMESIZE_RAW * sectors_read) / 4; i++) {
	  vorbbuf[0][i] = ((buffer[i * 4 + 1] << 8) | (0x00ff&(int)buffer[i * 4])) / 32768.f;
	  vorbbuf[1][i] = ((buffer[i * 4 + 3] << 8) | (0x00ff&(int)buffer[i * 4 + 2])) / 32768.f;
	}

	int samples_read = sectors_read * (CD_FRAMESAMPLES / 2);
	samplesdone += samples_read;
	// progress every 60 pages
	if (packetsdone >= 60) {
	  packetsdone = 0;
	  time = timer_time (timer);
	  update_statistics (total_samples_per_channel, samplesdone, time, track,
			     tracktot, 0, filenames);
	}
	vorbis_analysis_wrote (&vd, i);
      }
	  
      free (buffer);
      sector += sectors_read;
	  
      while (vorbis_analysis_blockout (&vd, &vb) == 1) {
	vorbis_analysis (&vb, &op);
	vorbis_bitrate_addblock (&vb);

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

	  while (!eos) {
	    int result = ogg_stream_pageout (&os, &og);
	    if (result == 0) {
	      break;
	    }
	    ret = write_page (&og, out);
	    if (ret != og.header_len + og.body_len) {
	      log_msg ("Failed writing data to output stream", FL, FN, LN);
	      ret = -1;
	    } else
	      bytes_written += ret;

	    if (ogg_page_eos (&og)) {
	      eos = 1;
	    }
	  }
	}
      }
    }
  }
  ret = 0;

  update_statistics (total_samples_per_channel, samplesdone, time, track,
		     tracktot, 0, filenames);
  
  ogg_stream_clear (&os);
  vorbis_block_clear (&vb);
  vorbis_dsp_clear (&vd);
  vorbis_comment_clear (&vc);
  vorbis_info_clear (&vi);
  vorbis_comment_clear (&vc);
  time_elapsed = timer_time (timer);
  end_func (time_elapsed, rate, samplesdone, bytes_written);
  timer_clear (timer);
  fclose (out);
  
  return ret;
}
Beispiel #11
0
encoder_state *encode_initialise(int channels, int rate, int managed,
        int min_br, int nom_br, int max_br, float quality, vorbis_comment *vc)
{
    encoder_state *s = calloc(1, sizeof(encoder_state));
    ogg_packet h1,h2,h3;

    /* Have vorbisenc choose a mode for us */
    vorbis_info_init(&s->vi);

    if (max_br < 0 && nom_br < 0 && min_br < 0)
       managed = 0;
    if (managed == 0 && nom_br >= 0)
        if (min_br >= 0 || max_br >= 0)
            managed = 1;
    do
    {
        if (managed)
        {
            LOG_INFO5("Encoder initialising with bitrate management: %d "
                    "channels, %d Hz, minimum bitrate %d, nominal %d, "
                    "maximum %d", channels, rate, min_br, nom_br, max_br);

            if (vorbis_encode_setup_managed (&s->vi, channels,
                        rate, max_br, nom_br, min_br))
                break;
        }
        else
        {
            if (nom_br < 0)
            {
                LOG_INFO3("Encoder initialising in VBR mode: %d channel(s), "
                        "%d Hz, quality %f", channels, rate, quality);
                if (min_br > 0 || max_br > 0)
                    LOG_INFO0("ignoring min/max bitrate, not supported in VBR "
                            "mode, use nominal-bitrate instead");
                if (vorbis_encode_setup_vbr(&s->vi, channels, rate, quality*0.1))
                    break;

#if 0
                if (max_br > 0 || min_br > 0)
                {
                    struct ovectl_ratemanage_arg ai;
                    if (vorbis_encode_ctl(&s->vi, OV_ECTL_RATEMANAGE_GET, &ai))
                        break;
                    ai.bitrate_hard_min = min_br;
                    ai.bitrate_hard_max = max_br;
                    ai.management_active = 1;
                    if (vorbis_encode_ctl(&s->vi, OV_ECTL_RATEMANAGE_SET, &ai))
                        break;
                }
#endif
            }
            else
            {
                LOG_INFO3("Encoder initialising in VBR mode: %d "
                        "channels, %d Hz, nominal %d", channels, rate, nom_br);
                if (vorbis_encode_setup_managed (&s->vi, channels,
                            rate, max_br, nom_br, max_br))
                    break;
                if (vorbis_encode_ctl (&s->vi, OV_ECTL_RATEMANAGE_SET, NULL))
                    break;
            }
        }
        if (vorbis_encode_setup_init(&s->vi))
            break;

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

        ogg_stream_init(&s->os, _get_serial());

        vorbis_analysis_headerout(&s->vd, vc, &h1,&h2,&h3);
        ogg_stream_packetin(&s->os, &h1);
        ogg_stream_packetin(&s->os, &h2);
        ogg_stream_packetin(&s->os, &h3);

        s->in_header = 1;
        s->samplerate = rate;
        s->samples_in_current_page = 0;
        s->prevgranulepos = 0;

        return s;
    } while (0);

    LOG_INFO0("Failed to configure encoder, verify settings");
    vorbis_info_clear(&s->vi);
    free (s);
    return NULL;
}
Beispiel #12
0
HOTSPOT PUBLIC SW32 vorbis_encode( const char *filename, void *data, W32 size, W32 in_channels, W32 in_samplesize,
			   W32 rate, W32 quality, W32 max_bitrate, W32 min_bitrate  )
{
	FILE			*fp;
	ogg_stream_state	os;
	ogg_page 		og;
	ogg_packet 		op;

	vorbis_dsp_state	vd;
	vorbis_block		vb;
	vorbis_info		vi;

	ogg_packet		header_main;
	ogg_packet		header_comments;
	ogg_packet		header_codebooks;
	SW32			result;
	W32			serialno = 0;

	vorbis_comment		comments;

	SW32			ret = 0;
	SW32			eos;
	W32			samplesdone = 0;
	W32			packetsdone = 0;
	W32			bytes_written = 0;



	fp = fopen( filename, "wb" );
	if( fp == NULL )
	{
		return 0;
	}

	memset( &comments, 0, sizeof( comments ) );

	channels = in_channels;
	samplesize = in_samplesize;
	ptrCurrent = (PW8)data;
	ptrEnd = (PW8)data + size;


	vorbis_info_init( &vi );

	if( vorbis_encode_setup_vbr( &vi, channels, rate, quality ) )
	{
		fprintf( stderr, "Mode initialisation failed: invalid parameters for quality\n" );
		vorbis_info_clear( &vi );
// Añadido como consejo de cppcheck.
		fclose(fp);
		return 1;
	}

	/* do we have optional hard quality restrictions? */
	if( max_bitrate > 0 || min_bitrate > 0 )
	{
		struct ovectl_ratemanage_arg ai;

		vorbis_encode_ctl( &vi, OV_ECTL_RATEMANAGE_GET, &ai );

		ai.bitrate_hard_min = min_bitrate;
		ai.bitrate_hard_max = max_bitrate;
		ai.management_active = 1;

		vorbis_encode_ctl( &vi, OV_ECTL_RATEMANAGE_SET, &ai );
	}

	/* Turn off management entirely (if it was turned on). */
	vorbis_encode_ctl( &vi, OV_ECTL_RATEMANAGE_SET, NULL );


	vorbis_encode_setup_init( &vi );

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

	ogg_stream_init( &os, serialno );

	/* Now, build the three header packets and send through to the stream
	   output stage (but defer actual file output until the main encode loop) */


	/* Build the packets */
	ret = vorbis_analysis_headerout( &vd, &comments,
			&header_main, &header_comments, &header_codebooks );

	/* And stream them out */
	ogg_stream_packetin( &os, &header_main );
	ogg_stream_packetin( &os, &header_comments );
	ogg_stream_packetin( &os, &header_codebooks );

	while( (result = ogg_stream_flush( &os, &og )) )
	{
		ret = fwrite( og.header, 1, og.header_len, fp );
		ret += fwrite( og.body, 1, og.body_len, fp );

		if(ret != og.header_len + og.body_len)
		{
			fprintf( stderr, "[vorbis_encode]: Failed writing header to output stream\n") ;
			ret = 1;

			goto cleanup; /* Bail and try to clean up stuff */
		}
	}


	eos = 0;

	/* Main encode loop - continue until end of file */
	while( ! eos )
	{
		float **buffer = vorbis_analysis_buffer( &vd, READSIZE );
		SW32 samples_read = read_samples( buffer, READSIZE );

		if( samples_read == 0 )
		{
			/* Tell the library that we wrote 0 bytes - signalling the end */
			vorbis_analysis_wrote( &vd, 0 );
		}
		else
		{
			samplesdone += samples_read;

			/* Call progress update every 40 pages */
			if( packetsdone >= 40 )
			{
				packetsdone = 0;

				// progress bar here
			}

			/* Tell the library how many samples (per channel) we wrote
			   into the supplied buffer */
			vorbis_analysis_wrote( &vd, samples_read );
		}

		/* While we can get enough data from the library to analyse, one
		   block at a time... */
		while( vorbis_analysis_blockout( &vd, &vb ) == 1 )
		{

			/* Do the main analysis, creating a packet */
			vorbis_analysis( &vb, NULL );
			vorbis_bitrate_addblock( &vb );

			while( vorbis_bitrate_flushpacket( &vd, &op ) )
			{
				/* Add packet to bitstream */
				ogg_stream_packetin( &os, &op );
				packetsdone++;

				/* If we've gone over a page boundary, we can do actual output,
				   so do so (for however many pages are available) */

				while( ! eos )
				{
					SW32 result = ogg_stream_pageout( &os, &og );
					if( ! result )
					{
						break;
					}

					ret = fwrite( og.header, 1, og.header_len, fp );
					ret += fwrite( og.body, 1, og.body_len, fp );

					if(ret != og.header_len + og.body_len)
					{
						fprintf( stderr, "[vorbis_encode]: Failed writing data to output stream\n" );
						ret = 1;

						goto cleanup; /* Bail */
					}
					else
					{
						bytes_written += ret;
					}

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


cleanup:

	fclose( fp );

	ogg_stream_clear( &os );

	vorbis_block_clear( &vb );
	vorbis_dsp_clear( &vd );
	vorbis_info_clear( &vi );

	return 0;
}
Beispiel #13
0
int encvorbisInit(hb_work_object_t *w, hb_job_t *job)
{
    hb_work_private_t *pv = calloc(1, sizeof(hb_work_private_t));
    hb_audio_t *audio = w->audio;
    w->private_data = pv;
    pv->job = job;

    int i;
    ogg_packet header[3];

    hb_log("encvorbis: opening libvorbis");

    /* init */
    for (i = 0; i < 3; i++)
    {
        // Zero vorbis headers so that we don't crash in mk_laceXiph
        // when vorbis_encode_setup_managed fails.
        memset(w->config->vorbis.headers[i], 0, sizeof(ogg_packet));
    }
    vorbis_info_init(&pv->vi);

    pv->out_discrete_channels =
        hb_mixdown_get_discrete_channel_count(audio->config.out.mixdown);

    if (audio->config.out.bitrate > 0)
    {
        if (vorbis_encode_setup_managed(&pv->vi, pv->out_discrete_channels,
                                        audio->config.out.samplerate, -1,
                                        audio->config.out.bitrate * 1000, -1))
        {
            hb_error("encvorbis: vorbis_encode_setup_managed() failed");
            *job->die = 1;
            return -1;
        }
    }
    else if (audio->config.out.quality != HB_INVALID_AUDIO_QUALITY)
    {
        // map VBR quality to Vorbis API (divide by 10)
        if (vorbis_encode_setup_vbr(&pv->vi, pv->out_discrete_channels,
                                    audio->config.out.samplerate,
                                    audio->config.out.quality / 10))
        {
            hb_error("encvorbis: vorbis_encode_setup_vbr() failed");
            *job->die = 1;
            return -1;
        }
    }

    if (vorbis_encode_ctl(&pv->vi, OV_ECTL_RATEMANAGE2_SET, NULL) ||
        vorbis_encode_setup_init(&pv->vi))
    {
        hb_error("encvorbis: vorbis_encode_ctl(ratemanage2_set) OR vorbis_encode_setup_init() failed");
        *job->die = 1;
        return -1;
    }

    /* add a comment */
    vorbis_comment_init(&pv->vc);
    vorbis_comment_add_tag(&pv->vc, "Encoder", "HandBrake");
    vorbis_comment_add_tag(&pv->vc, "LANGUAGE", w->config->vorbis.language);

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

    /* get the 3 headers */
    vorbis_analysis_headerout(&pv->vd, &pv->vc,
                              &header[0], &header[1], &header[2]);
    for (i = 0; i < 3; i++)
    {
        memcpy(w->config->vorbis.headers[i], &header[i], sizeof(ogg_packet));
        memcpy(w->config->vorbis.headers[i] + sizeof(ogg_packet),
               header[i].packet, header[i].bytes);
    }

    pv->input_samples = pv->out_discrete_channels * OGGVORBIS_FRAME_SIZE;
    audio->config.out.samples_per_frame = OGGVORBIS_FRAME_SIZE;
    pv->buf = malloc(pv->input_samples * sizeof(float));

    pv->list = hb_list_init();

    // channel remapping
    uint64_t layout = hb_ff_mixdown_xlat(audio->config.out.mixdown, NULL);
    pv->remap_table = hb_audio_remap_build_table(layout, &hb_vorbis_chan_map,
                                                 audio->config.in.channel_map);
    if (pv->remap_table == NULL)
    {
        hb_error("encvorbisInit: hb_audio_remap_build_table() failed");
        *job->die = 1;
        return -1;
    }

    return 0;
}