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