All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.axet.libvorbis.Jvorbis_info Maven / Gradle / Ivy

package com.github.axet.libvorbis;

import java.io.UnsupportedEncodingException;

import com.github.axet.libvorbis.modes.*;

import com.github.axet.libogg.Jogg_packet;
import com.github.axet.libogg.Joggpack_buffer;

/**
vorbis_info contains all the setup information specific to the
specific compression/decompression mode in progress (eg,
psychoacoustic settings, channel setup, options, codebook
etc). vorbis_info and substructures are in backends.h.
*/
public final class Jvorbis_info {
	static final int      VI_TRANSFORMB = 1;
	private static final int VI_WINDOWB = 1;
	private static final int VI_TIMEB   = 1;
	private static final int VI_FLOORB  = 2;
	private static final int VI_RESB    = 3;
	private static final int VI_MAPB    = 1;
	//
	static final int PACKETBLOBS = 15;
	//
	public int version = 0;
	public int channels = 0;
	public int rate = 0;

	/* The below bitrate declarations are *hints*.
	 Combinations of the three values carry the following implications:

	 all three set to the same value:
	   implies a fixed rate bitstream
	 only nominal set:
	   implies a VBR stream that averages the nominal bitrate.  No hard
	   upper/lower limit
	 upper and or lower set:
	   implies a VBR bitstream that obeys the bitrate limits. nominal
	   may also be set to give a nominal rate.
	 none set:
	   the coder does not care to speculate.
	*/

	int bitrate_upper   = 0;
	int bitrate_nominal = 0;
	int bitrate_lower   = 0;
	int bitrate_window  = 0;

	Jcodec_setup_info codec_setup = null;

	/************************* encoder settings *************************/
	/* a few static coder conventions */
	private static final Jvorbis_info_mode _mode_template[] = {// [2]
		new Jvorbis_info_mode( 0, 0, 0, 0 ),
		new Jvorbis_info_mode( 1, 0, 0, 1 )
	};

	private static final Jve_setup_data_template setup_list[] = {
		Jsetup_44.ve_setup_44_stereo,
		Jsetup_44p51.ve_setup_44_51,
		Jsetup_44u.ve_setup_44_uncoupled,

		Jsetup_32.ve_setup_32_stereo,
		Jsetup_32.ve_setup_32_uncoupled,

		Jsetup_22.ve_setup_22_stereo,
		Jsetup_22.ve_setup_22_uncoupled,
		Jsetup_16.ve_setup_16_stereo,
		Jsetup_16.ve_setup_16_uncoupled,

		Jsetup_11.ve_setup_11_stereo,
		Jsetup_11.ve_setup_11_uncoupled,
		Jsetup_8.ve_setup_8_stereo,
		Jsetup_8.ve_setup_8_uncoupled,

		Jsetup_X.ve_setup_X_stereo,
		Jsetup_X.ve_setup_X_uncoupled,
		Jsetup_X.ve_setup_XX_stereo,
		Jsetup_X.ve_setup_XX_uncoupled,
		null
	};

	private final void clear() {
		version  = 0;
		channels = 0;
		rate = 0;
		bitrate_upper   = 0;
		bitrate_nominal = 0;
		bitrate_lower  = 0;
		bitrate_window = 0;
		codec_setup = null;
	}

	// info.c
	/** blocksize 0 is guaranteed to be short, 1 is guaranteed to be long.
	   They may be equal, but short will never ge greater than long */
	final int vorbis_info_blocksize(final int zo) {
		final Jcodec_setup_info ci = this.codec_setup;
		return ci != null ? ci.blocksizes[zo] : -1;
	}

	/** used by synthesis, which has a full, alloced vi */
	public final void vorbis_info_init() {
		clear();
		this.codec_setup = new Jcodec_setup_info();
	}

	public final void vorbis_info_clear() {
		/*final Jcodec_setup_info ci = this.m_codec_setup;
		int i;

		if( ci != null ) {

			for( i = 0; i < ci.modes; i++ )
				if( ci.mode_param[i] != null ) ci.mode_param[i] = null;

			for( i = 0; i < ci.maps; i++ ) // unpack does the range checking
				if( ci.map_param[i] != null ) // this may be cleaning up an aborted
									// unpack, in which case the below type
									// cannot be trusted
					//Jregistry._mapping_P[ ci.map_type[i] ].free_info( ci.map_param[i] );
					ci.map_param[i] = null;

			for( i = 0; i < ci.floors; i++ ) // unpack does the range checking
				if( ci.floor_param[i] != null ) // this may be cleaning up an aborted
									// unpack, in which case the below type
									// cannot be trusted
					//Jregistry._floor_P[ ci.floor_type[i] ].free_info( ci.floor_param[i] );
					ci.floor_param[i] = null;

			for( i = 0; i < ci.residues; i++ ) // unpack does the range checking
				if( ci.residue_param[i] != null ) // this may be cleaning up an aborted
									// unpack, in which case the below type
									// cannot be trusted
					//Jregistry._residue_P[ ci.residue_type[i] ].free_info( ci.residue_param[i] );
					ci.residue_param[i] = null;

			for( i = 0; i < ci.books; i++ ) {
				if( ci.book_param[i] != null ) {
					// knows if the book was not alloced
					ci.book_param[i].vorbis_staticbook_destroy();
				}
				if( ci.fullbooks != null )
					ci.fullbooks[i].vorbis_book_clear();
			}
			if( ci.fullbooks != null )
				ci.fullbooks = null;

			for( i = 0; i < ci.psys; i++ )
				ci.psy_param[i] = null;

			//ci = null;
		}*/

		clear();
	}

	/** Header packing/unpacking */
	private final int _vorbis_unpack_info(final Joggpack_buffer opb) {
		final Jcodec_setup_info ci = this.codec_setup;
		if( ci == null ) {
			return (Jcodec.OV_EFAULT);
		}

		this.version = opb.oggpack_read( 32 );
		if( this.version != 0 ) {
			return (Jcodec.OV_EVERSION);
		}

		this.channels = opb.oggpack_read( 8 );
		this.rate = opb.oggpack_read( 32 );

		this.bitrate_upper = opb.oggpack_read( 32 );
		this.bitrate_nominal = opb.oggpack_read( 32 );
		this.bitrate_lower = opb.oggpack_read( 32 );

		final int[] blocksizes = ci.blocksizes;// java
		blocksizes[0] = 1 << opb.oggpack_read( 4 );
		blocksizes[1] = 1 << opb.oggpack_read( 4 );

		if( this.rate < 1 || this.channels < 1 || blocksizes[0] < 64 ||
			blocksizes[1] < blocksizes[0] || blocksizes[1] > 8192 ||

			opb.oggpack_read( 1 ) != 1 ) {/* EOP check */
//err_out:
			vorbis_info_clear();
			return (Jcodec.OV_EBADHEADER);
		}
		return (0);
	}

	/** all of the real encoding details are here.  The modes, books,
	   everything */
	private final int _vorbis_unpack_books(final Joggpack_buffer opb) {
		final Jcodec_setup_info ci = this.codec_setup;

		/* codebooks */
		ci.books = opb.oggpack_read( 8 ) + 1;
		if( ci.books <= 0 ) {
			vorbis_info_clear();
			return (Jcodec.OV_EBADHEADER);
		}
		for( int i = 0, ie = ci.books; i < ie; i++ ) {
			ci.book_param[i] = Jstatic_codebook.vorbis_staticbook_unpack( opb );
			if( ci.book_param[i] == null ) {
				vorbis_info_clear();
				return (Jcodec.OV_EBADHEADER);
			}
		}

		/* time backend settings; hooks are unused */
		{
			final int times = opb.oggpack_read( 6 ) + 1;
			if( times <= 0 ) {
				vorbis_info_clear();
				return (Jcodec.OV_EBADHEADER);
			}
			for( int i = 0; i < times; i++ ) {
				final int test = opb.oggpack_read( 16 );
				if( test < 0 || test >= VI_TIMEB ) {
					vorbis_info_clear();
					return (Jcodec.OV_EBADHEADER);
				}
			}
		}

		/* floor backend settings */
		ci.floors = opb.oggpack_read( 6 ) + 1;
		if( ci.floors <= 0 ) {
			vorbis_info_clear();
			return (Jcodec.OV_EBADHEADER);
		}
		final Jvorbis_func_floor[] floor_p = Jcodec._floor_P;// java
		for( int i = 0, ie = ci.floors; i < ie; i++ ) {
			final int t = opb.oggpack_read( 16 );
			ci.floor_type[i] = t;
			if( t < 0 || t >= VI_FLOORB ) {
				vorbis_info_clear();
				return (Jcodec.OV_EBADHEADER);
			}
			ci.floor_param[i] = floor_p[ t ].unpack( this, opb );
			if( ci.floor_param[i] == null ) {
				vorbis_info_clear();
				return (Jcodec.OV_EBADHEADER);
			}
		}

		/* residue backend settings */
		ci.residues = opb.oggpack_read( 6 ) + 1;
		if( ci.residues <= 0 ) {
			vorbis_info_clear();
			return (Jcodec.OV_EBADHEADER);
		}
		final Jvorbis_func_residue[] residue_p = Jcodec._residue_P;// java
		for( int i = 0; i < ci.residues; i++ ) {
			final int t = opb.oggpack_read( 16 );
			ci.residue_type[i] = t;
			if( t < 0 || t >= VI_RESB ) {
				vorbis_info_clear();
				return (Jcodec.OV_EBADHEADER);
			}
			ci.residue_param[i] = residue_p[ t ].unpack( this, opb );
			if( ci.residue_param[i] == null ) {
				vorbis_info_clear();
				return (Jcodec.OV_EBADHEADER);
			}
		}

		/* map backend settings */
		ci.maps = opb.oggpack_read( 6 ) + 1;
		if( ci.maps <= 0 ) {
			vorbis_info_clear();
			return (Jcodec.OV_EBADHEADER);
		}
		final Jvorbis_func_mapping[] mapping_p = Jcodec._mapping_P;// java
		for( int i = 0, ie = ci.maps; i < ie; i++ ) {
			final int t = opb.oggpack_read( 16 );
			ci.map_type[i] = t;
			if( t < 0 || t >= VI_MAPB ) {
				vorbis_info_clear();
				return (Jcodec.OV_EBADHEADER);
			}
			ci.map_param[i] = mapping_p[ t ].unpack( this, opb );
			if( ci.map_param[i] == null ) {
				vorbis_info_clear();
				return (Jcodec.OV_EBADHEADER);
			}
		}

		/* mode settings */
		ci.modes = opb.oggpack_read( 6 ) + 1;
		if( ci.modes <= 0 ) {
			vorbis_info_clear();
			return (Jcodec.OV_EBADHEADER);
		}
		for( int i = 0, ie = ci.modes; i < ie; i++ ) {
			final Jvorbis_info_mode vim = new Jvorbis_info_mode();
			vim.blockflag = opb.oggpack_read( 1 );
			vim.windowtype = opb.oggpack_read( 16 );
			vim.transformtype = opb.oggpack_read( 16 );
			vim.mapping = opb.oggpack_read( 8 );
			ci.mode_param[i] = vim;

			if( vim.windowtype >= VI_WINDOWB ||
				vim.transformtype >= VI_WINDOWB ||
				vim.mapping >= ci.maps ||
				vim.mapping < 0 )
			{
				vorbis_info_clear();
				return (Jcodec.OV_EBADHEADER);
			}
		}

		if( opb.oggpack_read( 1 ) != 1 ) {/* top level EOP check */
			vorbis_info_clear();
			return (Jcodec.OV_EBADHEADER);
		}
		return (0);
//err_out:
//		vorbis_info_clear( vi );
//		return (Jcodec.OV_EBADHEADER);
	}

	static final void _v_writestring(final Joggpack_buffer o, final byte[] s, int bytes ) {

		for( int i = 0; bytes-- > 0; ) {
			o.oggpack_write( s[i++], 8 );
		}
	}

	static final void _v_readstring(final Joggpack_buffer o, final String[] strings, final int offset, int bytes ) {
		final byte[] buf = new byte[bytes];
		for( int i = 0; bytes-- > 0; ) {
			buf[i++] = (byte)o.oggpack_read( 8 );
		}
		try { strings[offset] = new String( buf, Jvorbis_comment.TEXT_ENCODING );
		} catch (final UnsupportedEncodingException e) {}
	}

	static final void _v_readstring(final Joggpack_buffer o, final byte[] buf, int bytes ) {
		for( int i = 0; bytes-- > 0; ) {
			buf[i++] = (byte)o.oggpack_read( 8 );
		}
	}

	/* pack side **********************************************************/
	/* helpers */
	final int _vorbis_pack_info(final Joggpack_buffer opb) {
		final Jcodec_setup_info ci = this.codec_setup;
		if( ci == null ||
				ci.blocksizes[0] < 64 ||
				ci.blocksizes[1] < ci.blocksizes[0] ) {
			return (Jcodec.OV_EFAULT);
		}

		/* preamble */
		opb.oggpack_write( 0x01, 8 );
		_v_writestring( opb, Jvorbis_comment.vorbis, 6 );

		/* basic information about the stream */
		opb.oggpack_write( 0x00, 32 );
		opb.oggpack_write( this.channels, 8 );
		opb.oggpack_write( this.rate, 32 );

		opb.oggpack_write( this.bitrate_upper, 32 );
		opb.oggpack_write( this.bitrate_nominal, 32 );
		opb.oggpack_write( this.bitrate_lower, 32 );

		opb.oggpack_write( Jcodec.ov_ilog( ci.blocksizes[0] - 1 ), 4 );
		opb.oggpack_write( Jcodec.ov_ilog( ci.blocksizes[1] - 1 ), 4 );
		opb.oggpack_write( 1, 1 );

		return (0);
	}

	final int _vorbis_pack_books(final Joggpack_buffer opb) {
		final Jcodec_setup_info ci = this.codec_setup;
		if( ci == null ) {
			return (Jcodec.OV_EFAULT);
		}

		opb.oggpack_write( 0x05, 8 );
		_v_writestring( opb, Jvorbis_comment.vorbis, 6 );

		/* books */
		opb.oggpack_write( ci.books - 1, 8 );
		final Jstatic_codebook[] book_param = ci.book_param;// java
		for( int i = 0, ie = ci.books; i < ie; i++ ) {
			if( book_param[i].vorbis_staticbook_pack( opb ) != 0 ) {
				return -1;//goto err_out;
			}
		}

		/* times; hook placeholders */
		opb.oggpack_write( 0, 6 );
		opb.oggpack_write( 0, 16 );

		/* floors */
		opb.oggpack_write( ci.floors - 1, 6 );
		int[] tmp = ci.floor_type;// java
		final Jvorbis_func_floor[] floor_p = Jcodec._floor_P;// java
		final Jvorbis_info_floor[] floor_param = ci.floor_param;// java
		for( int i = 0, ie = ci.floors; i < ie; i++ ) {
			final int t = tmp[i];
			opb.oggpack_write( t, 16 );
			final Jvorbis_func_floor f = floor_p[t];
			if( f.is_pack_supported ) {
				f.pack( floor_param[i], opb );
			}
			else {
				return -1;//goto err_out;
			}
		}

		/* residues */
		opb.oggpack_write( ci.residues - 1, 6 );
		tmp = ci.residue_type;// java
		final Jvorbis_func_residue[] residue_p = Jcodec._residue_P;// java
		final Jvorbis_info_residue[] residue_param = ci.residue_param;// java
		for( int i = 0, ie = ci.residues; i < ie; i++ ) {
			final int type = tmp[i];// java
			opb.oggpack_write( type, 16 );
			// FIXME why no checking for null? see residue0_exportbundle
			residue_p[ type ].pack( residue_param[i], opb );
		}

		/* maps */
		opb.oggpack_write( ci.maps - 1, 6 );
		tmp = ci.map_type;// java
		final Jvorbis_func_mapping[] mapping_p = Jcodec._mapping_P;// java
		final Jvorbis_info_mapping[] map_param = ci.map_param;// java
		for( int i = 0, ie = ci.maps; i < ie; i++ ) {
			final int type = tmp[i];// java
			opb.oggpack_write( type, 16 );
			mapping_p[ type ].pack( this, map_param[i], opb );
		}

		/* modes */
		opb.oggpack_write( ci.modes - 1, 6 );
		final Jvorbis_info_mode[] mode_param = ci.mode_param;// java
		for( int i = 0, ie = ci.modes; i < ie; i++ ) {
			final Jvorbis_info_mode vim = mode_param[i];
			opb.oggpack_write( vim.blockflag, 1 );
			opb.oggpack_write( vim.windowtype, 16 );
			opb.oggpack_write( vim.transformtype, 16 );
			opb.oggpack_write( vim.mapping, 8 );
		}
		opb.oggpack_write( 1, 1 );

		return (0);
//err_out:
//		return (-1);
	}

	/** Is this packet a vorbis ID header? */
	public static final boolean vorbis_synthesis_idheader(final Jogg_packet op) {
		if( op != null ) {
			final Joggpack_buffer opb = new Joggpack_buffer();
			opb.oggpack_readinit( op.packet_base, op.packet, op.bytes );

			if( ! op.b_o_s ) {
				return false; /* Not the initial packet */
			}

			if( opb.oggpack_read( 8 ) != 1 ) {
				return false; /* not an ID header */
			}

			final byte buffer[] = new byte[6];// already zeroed
			_v_readstring( opb, buffer, 6 );
			if( buffer[0] != 'v' || buffer[1] != 'o' || buffer[2] != 'r' ||
				buffer[3] != 'b' || buffer[4] != 'i' || buffer[5] != 's' ) {
				return false; /* not vorbis */
			}

			return true;
		}

		return false;
	}

	/** The Vorbis header is in three packets; the initial small packet in
	   the first page that identifies basic parameters, a second packet
	   with bitstream comments and a third packet that holds the
	   codebook. */
	public static final int vorbis_synthesis_headerin(final Jvorbis_info vi, final Jvorbis_comment vc, final Jogg_packet op) {

		if( op != null) {
			final Joggpack_buffer opb = new Joggpack_buffer();
			opb.oggpack_readinit( op.packet_base, op.packet, op.bytes );

			/* Which of the three types of header is this? */
			/* Also verify header-ness, vorbis */
			{
				final byte buffer[] = new byte[6];// already zeroed
				final int packtype = opb.oggpack_read( 8 );
				_v_readstring( opb, buffer, 6 );
				if( buffer[0] != 'v' || buffer[1] != 'o' || buffer[2] != 'r' ||
					buffer[3] != 'b' || buffer[4] != 'i' || buffer[5] != 's' ) {
					/* not a vorbis header */
					return (Jcodec.OV_ENOTVORBIS);
				}
				switch( packtype ) {
				case 0x01: /* least significant *bit* is read first */
					if( ! op.b_o_s ) {
						/* Not the initial packet */
						return (Jcodec.OV_EBADHEADER);
					}
					if( vi.rate != 0 ) {
						/* previously initialized info header */
						return (Jcodec.OV_EBADHEADER);
					}

					return ( vi._vorbis_unpack_info( opb ) );

				case 0x03: /* least significant *bit* is read first */
					if( vi.rate == 0 ) {
						/* um... we didn't get the initial header */
						return (Jcodec.OV_EBADHEADER);
					}
					if( vc.vendor != null ) {
						/* previously initialized comment header */
						return (Jcodec.OV_EBADHEADER);
					}

					return ( vc._vorbis_unpack_comment( opb ) );

				case 0x05: /* least significant *bit* is read first */
					if( vi.rate == 0 || vc.vendor == null ) {
						/* um... we didn;t get the initial header or comments yet */
						return (Jcodec.OV_EBADHEADER);
					}
					if( vi.codec_setup == null ) {
						/* improperly initialized vorbis_info */
						return (Jcodec.OV_EFAULT);
					}
					if( vi.codec_setup.books > 0 ) {
						/* previously initialized setup header */
						return (Jcodec.OV_EBADHEADER);
					}

					return ( vi._vorbis_unpack_books( opb ) );

				default:
					/* Not a valid vorbis header type */
					return (Jcodec.OV_EBADHEADER);
					//break;
				}
			}
		}
		return (Jcodec.OV_EBADHEADER);
	}

	// bitrate.c
	/** compute bitrate tracking setup  */
	final void vorbis_bitrate_init(final Jbitrate_manager_state bm) {
		final Jcodec_setup_info ci = this.codec_setup;
		final Jbitrate_manager_info bi = ci.bi;

		bm.clear();// zeroed

		if( bi != null && (bi.reservoir_bits > 0) ) {
			final int ratesamples = this.rate;
			final int halfsamples = ci.blocksizes[0] >> 1;

			bm.short_per_long = ci.blocksizes[1] / ci.blocksizes[0];
			bm.managed = 1;

			bm.avg_bitsper = (int)Math.rint( 1. * bi.avg_rate * halfsamples / ratesamples );
			bm.min_bitsper = (int)Math.rint( 1. * bi.min_rate * halfsamples / ratesamples );
			bm.max_bitsper = (int)Math.rint( 1. * bi.max_rate * halfsamples / ratesamples );

			bm.avgfloat = (double)(PACKETBLOBS / 2);

			/* not a necessary fix, but one that leads to a more balanced
			typical initialization */
			{
				final int desired_fill = (int)(bi.reservoir_bits * bi.reservoir_bias);
				bm.minmax_reservoir = desired_fill;
				bm.avg_reservoir = desired_fill;
			}

		}
	}

	// psy.c
	final Jvorbis_look_psy_global _vp_global_look() {
		final Jcodec_setup_info ci = this.codec_setup;
		final Jvorbis_info_psy_global gi = ci.psy_g_param;
		final Jvorbis_look_psy_global look = new Jvorbis_look_psy_global();

		look.channels = this.channels;

		look.ampmax = -9999.f;
		look.gi = gi;
		return (look);
	}

	// synthesys.c
	public final int vorbis_packet_blocksize(final Jogg_packet op) {
		final Jcodec_setup_info ci = this.codec_setup;
		if( ci == null || ci.modes <= 0 ) {
			/* codec setup not properly intialized */
			return (Jcodec.OV_EFAULT);
		}

		final Joggpack_buffer  opb = new Joggpack_buffer();

		opb.oggpack_readinit( op.packet_base, op.packet, op.bytes );

		/* Check the packet type */
		if( opb.oggpack_read( 1 ) != 0 ) {
			/* Oops.  This is not an audio data packet */
			return (Jcodec.OV_ENOTAUDIO);
		}

		/* read our mode and pre/post windowsize */
		final int mode = opb.oggpack_read( Jcodec.ov_ilog( ci.modes - 1 ) );
		if( mode == -1 || null == ci.mode_param[mode] ) {
			return (Jcodec.OV_EBADPACKET);
		}
		return (ci.blocksizes[ ci.mode_param[mode].blockflag ]);
	}

	public final int vorbis_synthesis_halfrate(final boolean flag) {
		/* set / clear half-sample-rate mode */
		final Jcodec_setup_info ci = this.codec_setup;

		/* right now, our MDCT can't handle < 64 sample windows. */
		if( ci.blocksizes[0] <= 64 && flag ) {
			return -1;
		}
		ci.halfrate_flag = flag ? 1 : 0;
		return 0;
	}

	/** @return 1 or 0 */
	public final int vorbis_synthesis_halfrate_p() {
		return this.codec_setup.halfrate_flag;
	}

	// vorbisenc.c
	private final void vorbis_encode_floor_setup(final double s,// FIXME why int s?
					final Jstatic_codebook[][] books,
					final Jvorbis_info_floor1[] in,
					final int[] x)
	{
		final int is = (int)s;
		final Jvorbis_info_floor1 f = new Jvorbis_info_floor1( in[ x[is] ] );
		final Jcodec_setup_info ci = this.codec_setup;

		/* books */
		{
			final int partitions = f.partitions;
			int maxclass = -1;
			int maxbook = -1;
			int[] tmp = f.partitionclass;// java
			for( int i = 0; i < partitions; i++ ) {
				if( tmp[i] > maxclass ) {
					maxclass = tmp[i];
				}
			}
			int ci_books = ci.books;// java
			tmp = f.class_book;// java
			final int[][] class_subbook = f.class_subbook;// java
			final int[] class_subs = f.class_subs;// java
			for( int i = 0; i <= maxclass; i++ ) {
				int t = tmp[i];// java
				if( t > maxbook ) {
					maxbook = t;
				}
				t += ci_books;
				tmp[i] = t;
				final int sb[] = class_subbook[i];
				for( int k = 0, ke = (1 << class_subs[i]); k < ke; k++ ) {
					if( sb[k] > maxbook ) {
						maxbook = sb[k];
					}
					if( sb[k] >= 0 ) {
						sb[k] += ci_books;
					}
				}
			}

			final Jstatic_codebook[] book_param = ci.book_param;// java
			for( int i = 0; i <= maxbook; i++ ) {
				book_param[ci_books++] = (Jstatic_codebook)books[ x[is] ][i];
			}
			ci.books = ci_books;
		}

		/* for now, we're only using floor 1 */
		ci.floor_type[ci.floors] = 1;
		ci.floor_param[ci.floors] = f;
		ci.floors++;

		return;
	}

	private final void vorbis_encode_global_psych_setup(final double s,
					final Jvorbis_info_psy_global[] in,
					final double[] x)
	{
		int is = (int)s;
		double ds = s - is;
		final Jcodec_setup_info ci = this.codec_setup;
		final Jvorbis_info_psy_global g = ci.psy_g_param;

		g.copyFrom( in[(int)x[is]] );

		ds = x[is] * (1. - ds) + (double)x[is + 1] * ds;
		is = (int)ds;
		ds -= is;
		if( ds == 0 && is > 0 ) {
			is--;
			ds = 1.;
		}

		/* interpolate the trigger threshholds */
		final double ds1 = 1. - ds;// java
		Jvorbis_info_psy_global p = in[is];// java
		final float[] in_is_preecho_thresh = p.preecho_thresh;// java
		final float[] in_is_postecho_thresh = p.postecho_thresh;// java
		p = in[is + 1];// java
		final float[] in_is_preecho_thresh1 = p.preecho_thresh;// java
		final float[] in_is_postecho_thresh1 = p.postecho_thresh;// java
		final float[] g_preecho_thresh = g.preecho_thresh;// java
		final float[] g_postecho_thresh = g.postecho_thresh;// java
		for( int i = 0; i < 4; i++ ) {
			g_preecho_thresh[i] = (float)(in_is_preecho_thresh[i] * ds1 + in_is_preecho_thresh1[i] * ds);
			g_postecho_thresh[i] = (float)(in_is_postecho_thresh[i] * ds1 + in_is_postecho_thresh1[i] * ds);
		}
		g.ampmax_att_per_sec = (float)ci.hi.amplitude_track_dBpersec;
		return;
	}

	private final void vorbis_encode_global_stereo( final Jhighlevel_encode_setup hi, final Jadj_stereo[] p) {
		final float s = (float)hi.stereo_point_setting;
		final int is = (int)s;
		final double ds = s - is;
		final Jcodec_setup_info ci = this.codec_setup;
		final Jvorbis_info_psy_global g = ci.psy_g_param;

		final int[] sliding_lowpass0 = g.sliding_lowpass[0];// java
		final int[] sliding_lowpass1 = g.sliding_lowpass[1];// java
		final int blocksizes0 = ci.blocksizes[0];// java
		final int blocksizes1 = ci.blocksizes[1];// java
		if( p != null ) {
			Jadj_stereo a = p[is];// java
			System.arraycopy( a.pre, 0, g.coupling_prepointamp, 0, PACKETBLOBS );
			System.arraycopy( a.post, 0, g.coupling_postpointamp, 0, PACKETBLOBS );
			final float[] a_kHz = a.kHz;// java
			final float[] a_lowpasskHz = a.lowpasskHz;// java
			a = p[is + 1];// java
			final float[] a1_kHz = a.kHz;// java
			final float[] a1_lowpasskHz = a.lowpasskHz;// java

			final double ds1 = 1. - ds;// java
			float k1 = 1000.f / this.rate;// java
			final float k0 = k1 * blocksizes0;// java
			k1 *= blocksizes1;// java
			final int[] coupling_pointlimit0 = g.coupling_pointlimit[0];// java
			final int[] coupling_pointlimit1 = g.coupling_pointlimit[1];// java
			final int[] coupling_pkHz = g.coupling_pkHz;// java
			if( hi.managed ) {
				/* interpolate the kHz threshholds */
				for( int i = 0; i < PACKETBLOBS; i++ ) {
					float kHz = (float)(a_kHz[i] * ds1 + (double)a1_kHz[i] * ds);
					coupling_pointlimit0[i] = (int)(kHz * k0);
					coupling_pointlimit1[i] = (int)(kHz * k1);
					coupling_pkHz[i] = (int)kHz;

					kHz = (float)(a_lowpasskHz[i] * ds1 + (double)a1_lowpasskHz[i] * ds);
					sliding_lowpass0[i] = (int)(kHz * k0);
					sliding_lowpass1[i] = (int)(kHz * k1);
				}
			} else {
				float kHz = (float)(a_kHz[PACKETBLOBS / 2] * ds1 +
							(double)a1_kHz[PACKETBLOBS / 2] * ds);
				int kHz_k0 = (int)(kHz * k0);
				int kHz_k1 = (int)(kHz * k1);
				for( int i = 0; i < PACKETBLOBS; i++ ) {
					coupling_pointlimit0[i] = kHz_k0;
					coupling_pointlimit1[i] = kHz_k1;
					coupling_pkHz[i] = (int)kHz;
				}

				kHz = (float)(a_lowpasskHz[PACKETBLOBS / 2] * ds1 +
							(double)a1_lowpasskHz[PACKETBLOBS / 2] * ds);
				kHz_k0 = (int)(kHz * k0);
				kHz_k1 = (int)(kHz * k1);
				for( int i = 0; i < PACKETBLOBS; i++ ) {
					sliding_lowpass0[i] = kHz_k0;
					sliding_lowpass1[i] = kHz_k1;
				}
			}
		} else {
			for( int i = 0; i < PACKETBLOBS; i++ ) {
				sliding_lowpass0[i] = blocksizes0;
				sliding_lowpass1[i] = blocksizes1;
			}
		}
		return;
	}

	private final void vorbis_encode_psyset_setup(final double s,
					final int[] nn_start, final int[] nn_partition,
					final double[] nn_thresh, final int block)
	{
		final Jcodec_setup_info ci = this.codec_setup;

		if( block >= ci.psys ) {
			ci.psys = block + 1;
		}

		final Jvorbis_info_psy p = new Jvorbis_info_psy( Jpsych_44._psy_info_template );
		ci.psy_param[block] = p;
		p.blockflag = block >> 1;

		if( ci.hi.noise_normalize_p ) {
			final int is = (int)s;
			p.normal_p = true;
			p.normal_start = nn_start[is];
			p.normal_partition = nn_partition[is];
			p.normal_thresh = nn_thresh[is];
		}

		return;
	}

	private final void vorbis_encode_tonemask_setup(final double s, final int block,
					final Jatt3[] att, final int[] max, final Jvp_adjblock[] in)
	{
		final int is = (int)s;
		final double ds = s - is;
		final Jvorbis_info_psy p = this.codec_setup.psy_param[block];

		/* 0 and 2 are only used by bitmanagement, but there's no harm to always
		  filling the values in here */
		final double ds1 = 1. - ds;// java
		final Jatt3 a = att[is];// java
		final Jatt3 a1 = att[is + 1];// java
		final int[] att_is = a.att;// java
		final int[] att_is1 = a1.att;// java
		final float[] tone_masteratt = p.tone_masteratt;// java
		tone_masteratt[0] = (float)(att_is[0] * ds1 + (double)att_is1[0] * ds);
		tone_masteratt[1] = (float)(att_is[1] * ds1 + (double)att_is1[1] * ds);
		tone_masteratt[2] = (float)(att_is[2] * ds1 + (double)att_is1[2] * ds);
		p.tone_centerboost = (float)(a.boost * ds1 + (double)a1.boost * ds);
		p.tone_decay = (float)(a.decay * ds1 + (double)a1.decay * ds);

		p.max_curve_dB = (float)(max[is] * ds1 + (double)max[is + 1] * ds);

		final int[] inblock = in[is].block;// java
		final int[] inblock1 = in[is + 1].block;// java
		final float[] toneatt = p.toneatt;// java
		for( int i = 0; i < Jvorbis_look_psy.P_BANDS; i++ ) {
			toneatt[i] = (float)(inblock[i] * ds1 + (double)inblock1[i] * ds);
		}
		return;
	}

	private final void vorbis_encode_compand_setup(final double s, final int block,
					final Jcompandblock[] in, final double[] x) {
		int is = (int)s;
		double ds = s - is;
		final Jcodec_setup_info ci = this.codec_setup;
		final Jvorbis_info_psy p = ci.psy_param[block];

		ds = x[is] * (1. - ds) + x[is + 1] * ds;
		is = (int)ds;
		ds -= is;
		if( ds == 0 && is > 0 ) {
			is--;
			ds = 1.;
		}

		/* interpolate the compander settings */
		final double ds1 = 1. - ds;// java
		final int[] data = in[is].data;// java
		final int[] data1 = in[is + 1].data;// java
		final float[] noisecompand = p.noisecompand;// java
		for( int i = 0; i < Jvorbis_look_psy.NOISE_COMPAND_LEVELS; i++ ) {
			noisecompand[i] = (float)(data[i] * ds1 + (double)data1[i] * ds);
		}
		return;
	}

	private final void vorbis_encode_peak_setup( final double s, final int block,
					final int[] suppress) {
		final int is = (int)s;
		final double ds = s - is;
		final Jvorbis_info_psy p = this.codec_setup.psy_param[block];

		p.tone_abs_limit = (float)(suppress[is] * (1. - ds) + (double)suppress[is + 1] * ds);

		return;
	}

	private final void vorbis_encode_noisebias_setup(final double s, final int block,
					final int[] suppress, final Jnoise3[] in, final Jnoiseguard[] guard,
					final double userbias) {

		final int is = (int)s;
		final double ds = s - is;
		final double ds1 = 1. - ds;// java
		final Jvorbis_info_psy   p = this.codec_setup.psy_param[block];

		p.noisemaxsupp = (float)(suppress[is] * ds1 + (double)suppress[is + 1] * ds);
		p.noisewindowlomin = guard[block].lo;
		p.noisewindowhimin = guard[block].hi;
		p.noisewindowfixed = guard[block].fixed;

		final int[][] data = in[is].data;// java
		final int[][] data1 = in[is + 1].data;// java
		final float[][] noiseoff = p.noiseoff;// java
		for( int j = 0; j < Jvorbis_look_psy.P_NOISECURVES; j++ ) {
			final float[] nj = noiseoff[j];// java
			final int[] d = data[j];// java
			final int[] d1 = data1[j];// java
			for( int i = 0; i < Jvorbis_look_psy.P_BANDS; i++ ) {
				nj[i] = (float)(d[i] * ds1 + (double)d1[i] * ds);
			}
		}

		/* impulse blocks may take a user specified bias to boost the
		nominal/high noise encoding depth */
		for( int j = 0; j < Jvorbis_look_psy.P_NOISECURVES; j++ ) {
			final float[] nj = noiseoff[j];// java
			final float min = nj[0] + 6; /* the lowest it can go */
			for( int i = 0; i < Jvorbis_look_psy.P_BANDS; i++ ) {
				float n = nj[i];// java
				n += userbias;
				if( n < min ) {
					n = min;
				}
				nj[i] = n;
			}
		}

		return;
	}

	private final void vorbis_encode_ath_setup(final int block) {
		final Jcodec_setup_info ci = this.codec_setup;
		final Jvorbis_info_psy p = ci.psy_param[block];

		p.ath_adjatt = (float)ci.hi.ath_floating_dB;
		p.ath_maxatt = (float)ci.hi.ath_absolute_dB;
		return;
	}


	private static final int book_dup_or_new(final Jcodec_setup_info ci, final Jstatic_codebook book) {
		final Jstatic_codebook[] cb = ci.book_param;// java
		for( int i = 0, ie = ci.books; i < ie; i++ ) {
			if( cb[i] == book ) {
				return (i);
			}
		}

		return (ci.books++);
	}

	private final void vorbis_encode_blocksize_setup(final double s,
					final int[] shortb, final int[] longb) {

		final Jcodec_setup_info ci = this.codec_setup;
		final int is = (int)s;

		final int blockshort = shortb[is];
		final int blocklong = longb[is];
		ci.blocksizes[0] = blockshort;
		ci.blocksizes[1] = blocklong;
	}

	private final void vorbis_encode_residue_setup(
					final int number, final int block,
					final Jvorbis_residue_template res) {

		final Jcodec_setup_info ci = this.codec_setup;

		final Jvorbis_info_residue0 r = new Jvorbis_info_residue0( res.res );
		ci.residue_param[number] = r;

		if( ci.residues <= number ) {
			ci.residues = number + 1;
		}

		r.grouping = res.grouping;
		ci.residue_type[number] = res.res_type;

		/* fill in all the books */
		{
			int booklist = 0;
			final int partitions = r.partitions;// java

			// java: if-else changed
			final Jstatic_codebook[][] books;
			final Jstatic_codebook book_aux;
			if( ci.hi.managed ) {// FIXME don't cover the test
				books = res.books_base_managed.books;
				book_aux = res.book_aux_managed;
			} else {
				books = res.books_base.books;
				book_aux = res.book_aux;
			}

			final int[] secondstages = r.secondstages;// java
			for( int i = 0; i < partitions; i++ ) {
				int s = secondstages[i];// java
				final Jstatic_codebook[] b = books[i];// java
				for( int k = 0; k < 4; k++ ) {
					if( b[k] != null ) {
						s |= (1 << k);
					}
				}
				secondstages[i] = s;
			}

			r.groupbook = book_dup_or_new( ci, book_aux );
			final Jstatic_codebook[] book_param = ci.book_param;// java
			book_param[r.groupbook] = (Jstatic_codebook)book_aux;

			final int[] r_booklist = r.booklist;// java
			for( int i = 0; i < partitions; i++ ) {
				final Jstatic_codebook[] bi = books[i];// java
				for( int k = 0; k < 4; k++ ) {
					final Jstatic_codebook b = bi[k];// java
					if( b != null ) {
						final int bookid = book_dup_or_new( ci, b );
						r_booklist[booklist++] = bookid;
						book_param[bookid] = (Jstatic_codebook)b;
					}
				}
			}

		}

		/* lowpass setup/pointlimit */
		{
			double freq = ci.hi.lowpass_kHz * 1000.;
			final Jvorbis_info_floor1 f = (Jvorbis_info_floor1)ci.floor_param[block]; /* by convention */
			final double nyq = this.rate * 0.5;
			final int blocksize = ci.blocksizes[block] >>> 1;

			/* lowpass needs to be set in the floor and the residue. */
			if( freq > nyq ) {
				freq = nyq;
			}
			/* in the floor, the granularity can be very fine; it doesn't alter
			  the encoding structure, only the samples used to fit the floor
			  approximation */
			f.n = (int)(freq / nyq * blocksize);

			/* this res may by limited by the maximum pointlimit of the mode,
			  not the lowpass. the floor is always lowpass limited. */
			switch( res.limit_type ) {
			case 1: /* point stereo limited */
				if( ci.hi.managed ) {
					freq = ci.psy_g_param.coupling_pkHz[PACKETBLOBS - 1] * 1000.;
				} else {
					freq = ci.psy_g_param.coupling_pkHz[PACKETBLOBS / 2] * 1000.;
				}
				if( freq > nyq ) {
					freq = nyq;
				}
				break;
			case 2: /* LFE channel; lowpass at ~ 250Hz */
				freq = 250;
				break;
			default:
				/* already set */
				break;
			}

			/* in the residue, we're constrained, physically, by partition
			  boundaries.  We still lowpass 'wherever', but we have to round up
			  here to next boundary, or the vorbis spec will round it *down* to
			  previous boundary in encode/decode */
			if( ci.residue_type[number] == 2 ) {
				/* residue 2 bundles together multiple channels; used by stereo
				  and surround.  Count the channels in use */
				/* Multiple maps/submaps can point to the same residue.  In the case
				  of residue 2, they all better have the same number of
				  channels/samples. */
				int ch = 0;
				final int nchannels = this.channels;// java
				for( int i = 0, maps = ci.maps; i < maps && ch == 0; i++ ) {
					final Jvorbis_info_mapping0 mi = (Jvorbis_info_mapping0)ci.map_param[i];
					final int[] residuesubmap = mi.residuesubmap;// java
					final int[] chmuxlist = mi.chmuxlist;// java
					for( int j = 0, je = mi.submaps; j < je && ch == 0; j++ ) {
						if( residuesubmap[j] == number ) {
							for( int k = 0; k < nchannels; k++ ) {
								if( chmuxlist[k] == j ) {
									ch++;
								}
							}
						}
					}
				}

				r.end = (int)((freq / nyq * blocksize * ch) / r.grouping + .9) * /* round up only if we're well past */
									r.grouping;
				/* the blocksize and grouping may disagree at the end */
				ch *= blocksize;// java
				if( r.end > ch ) {
					r.end = ch / r.grouping * r.grouping;
				}

			} else {

				r.end = (int)((freq / nyq * blocksize) / r.grouping + .9) * /* round up only if we're well past */
									r.grouping;
				/* the blocksize and grouping may disagree at the end */
				if( r.end > blocksize ) {
					r.end = blocksize / r.grouping * r.grouping;
				}

			}

			if( r.end == 0 ) {
				r.end = r.grouping; /* LFE channel */
			}

		}
	}

	/** we assume two maps in this encoder */
	private final void vorbis_encode_map_n_res_setup(final double s,
					final Jvorbis_mapping_template[] maps) {

		final Jcodec_setup_info ci = this.codec_setup;
		int modes = 2;
		final int is = (int)s;
		final Jvorbis_info_mapping0[] map = maps[is].map;
		final Jvorbis_info_mode[] mode = _mode_template;
		final Jvorbis_residue_template[] res = maps[is].res;

		if( ci.blocksizes[0] == ci.blocksizes[1] ) {
			modes = 1;
		}

		for( int i = 0; i < modes; i++ ) {

			ci.mode_param[i] = new Jvorbis_info_mode( mode[i] );

			if( i >= ci.modes ) {
				ci.modes = i + 1;
			}

			ci.map_type[i] = 0;
			final Jvorbis_info_mapping0 mi = map[i];// java
			ci.map_param[i] = new Jvorbis_info_mapping0( mi );

			if( i >= ci.maps ) {
				ci.maps = i + 1;
			}

			final int[] residuesubmap = mi.residuesubmap;// java
			for( int j = 0, submaps = mi.submaps; j < submaps; j++ ) {
				final int r = residuesubmap[j];// java
				vorbis_encode_residue_setup( r, i, res[ r ] );
			}
		}
	}

	private final double setting_to_approx_bitrate() {
		final Jhighlevel_encode_setup hi = this.codec_setup.hi;
		final Jve_setup_data_template setup = (Jve_setup_data_template )hi.setup;

		final double[] r = setup.rate_mapping;

		if( r == null ) {
			return (-1);// FIXME is this correct return?
		}

		final int is = (int)hi.base_setting;
		final double ds = hi.base_setting - (double)is;
		return ((r[is] * (1. - ds) + r[is + 1] * ds) * this.channels);
	}

	// added Jhighlevel_encode_setup hi, return void
	private static final void get_setup_template(final int ch, final int srate,
					double req, final boolean q_or_bitrate,
					final Jhighlevel_encode_setup hi) {

		if( q_or_bitrate ) {
			req /= ch;
		}

		Jve_setup_data_template st;// jjava
		for( int i = 0; (st = setup_list[i]) != null; i++ ) {// java: while changed to for
			if( st.coupling_restriction == -1 ||
					st.coupling_restriction == ch ) {
				if( srate >= st.samplerate_min_restriction &&
						srate <= st.samplerate_max_restriction ) {
					final int mappings = st.mappings;
					final double[] map = (q_or_bitrate ?
									st.rate_mapping :
									st.quality_mapping);

					/* the template matches.  Does the requested quality mode
					  fall within this template's modes? */
					if( req < map[0] ) { ++i; continue; }
					if( req > map[ mappings ] ) { ++i; continue; }
					int j = 0;
					for( ; j < mappings; j++ ) {
						if( req >= map[j] && req < map[j + 1] ) {
							break;
						}
					}
					/* an all-points match */
					if( j == mappings ) {
						hi.base_setting = (double)j - .001;
					} else {
						final double low = map[j];
						final double high = map[j + 1];
						final double del = ((req - low) / (high - low));
						hi.base_setting = (double)j + del;
					}

					//return (setup_list[i]);
					hi.setup = st;
					return;
				}
			}
		}

		//return null;
		hi.setup = null;
	}

	/**
	 * This function performs the last stage of three-step encoding setup, as
	 * described in the API overview under managed bitrate modes.
	 * 

* Before this function is called, the {@link Jvorbis_info} struct should be * initialized by using vorbis_info_init() from the libvorbis API, one of * {@link #vorbis_encode_setup_managed} or {@link #vorbis_encode_setup_vbr} called to * initialize the high-level encoding setup, and {@link #vorbis_encode_ctl} * called if necessary to make encoding setup changes. * vorbis_encode_setup_init() finalizes the highlevel encoding structure into * a complete encoding setup after which the application may make no further * setup changes. *

* After encoding, vorbis_info_clear() should be called. * * @param vi Pointer to an initialized {@link Jvorbis_info} struct. * * @return Zero for success, and negative values for failure. * * @retval 0 Success. * @retval OV_EFAULT Internal logic fault; indicates a bug or heap/stack corruption. * * @retval OV_EINVAL Attempt to use vorbis_encode_setup_init() without first * calling one of vorbis_encode_setup_managed() or vorbis_encode_setup_vbr() to * initialize the high-level encoding setup * */ public final int vorbis_encode_setup_init() { final Jcodec_setup_info ci = this.codec_setup; // final Jhighlevel_encode_setup hi = ci.hi; if( ci == null ) {// FIXME check after using return (Jcodec.OV_EINVAL); } final Jhighlevel_encode_setup hi = ci.hi; int i0 = 0; if( ! hi.impulse_block_p ) { i0 = 1; } /* too low/high an ATH floater is nonsensical, but doesn't break anything */ if( hi.ath_floating_dB > -80 ) { hi.ath_floating_dB = -80; } if( hi.ath_floating_dB < -200 ) { hi.ath_floating_dB = -200; } /* again, bound this to avoid the app shooting itself int he foot too badly */ if( hi.amplitude_track_dBpersec > 0. ) { hi.amplitude_track_dBpersec = 0.; } if( hi.amplitude_track_dBpersec < -99999. ) { hi.amplitude_track_dBpersec = -99999.; } /* get the appropriate setup template; matches the fetch in previous stages */ final Jve_setup_data_template setup = (Jve_setup_data_template)hi.setup; if( setup == null ) { return (Jcodec.OV_EINVAL); } hi.set_in_stone = 1; /* choose block sizes from configured sizes as well as paying attention to long_block_p and short_block_p. If the configured short and long blocks are the same length, we set long_block_p and unset short_block_p */ vorbis_encode_blocksize_setup( hi.base_setting, setup.blocksize_short, setup.blocksize_long ); final boolean singleblock = ( ci.blocksizes[0] == ci.blocksizes[1] ); /* floor setup; choose proper floor params. Allocated on the floor stack in order; if we alloc only a single long floor, it's 0 */ final int[][] floor_mapping_list = setup.floor_mapping_list;// java for( int i = 0, ie = setup.floor_mappings; i < ie; i++ ) { vorbis_encode_floor_setup( hi.base_setting, setup.floor_books, setup.floor_params, floor_mapping_list[i] ); } /* setup of [mostly] short block detection and stereo*/ vorbis_encode_global_psych_setup( hi.trigger_setting, setup.global_params, setup.global_mapping ); vorbis_encode_global_stereo( hi, setup.stereo_modes ); /* basic psych setup and noise normalization */ vorbis_encode_psyset_setup( hi.base_setting, setup.psy_noise_normal_start[0], setup.psy_noise_normal_partition[0], setup.psy_noise_normal_thresh, 0 ); vorbis_encode_psyset_setup( hi.base_setting, setup.psy_noise_normal_start[0], setup.psy_noise_normal_partition[0], setup.psy_noise_normal_thresh, 1 ); if( ! singleblock ) { vorbis_encode_psyset_setup( hi.base_setting, setup.psy_noise_normal_start[1], setup.psy_noise_normal_partition[1], setup.psy_noise_normal_thresh, 2 ); vorbis_encode_psyset_setup( hi.base_setting, setup.psy_noise_normal_start[1], setup.psy_noise_normal_partition[1], setup.psy_noise_normal_thresh, 3 ); } /* tone masking setup */ vorbis_encode_tonemask_setup( hi.block[i0].tone_mask_setting, 0, setup.psy_tone_masteratt, setup.psy_tone_0dB, setup.psy_tone_adj_impulse ); vorbis_encode_tonemask_setup( hi.block[1].tone_mask_setting, 1, setup.psy_tone_masteratt, setup.psy_tone_0dB, setup.psy_tone_adj_other ); if( ! singleblock ) { vorbis_encode_tonemask_setup( hi.block[2].tone_mask_setting, 2, setup.psy_tone_masteratt, setup.psy_tone_0dB, setup.psy_tone_adj_other ); vorbis_encode_tonemask_setup( hi.block[3].tone_mask_setting, 3, setup.psy_tone_masteratt, setup.psy_tone_0dB, setup.psy_tone_adj_long ); } /* noise companding setup */ vorbis_encode_compand_setup( hi.block[i0].noise_compand_setting, 0, setup.psy_noise_compand, setup.psy_noise_compand_short_mapping ); vorbis_encode_compand_setup( hi.block[1].noise_compand_setting, 1, setup.psy_noise_compand, setup.psy_noise_compand_short_mapping ); if( ! singleblock ) { vorbis_encode_compand_setup( hi.block[2].noise_compand_setting, 2, setup.psy_noise_compand, setup.psy_noise_compand_long_mapping ); vorbis_encode_compand_setup( hi.block[3].noise_compand_setting, 3, setup.psy_noise_compand, setup.psy_noise_compand_long_mapping ); } /* peak guarding setup */ vorbis_encode_peak_setup( hi.block[i0].tone_peaklimit_setting, 0, setup.psy_tone_dBsuppress ); vorbis_encode_peak_setup( hi.block[1].tone_peaklimit_setting, 1, setup.psy_tone_dBsuppress ); if( ! singleblock ) { vorbis_encode_peak_setup( hi.block[2].tone_peaklimit_setting, 2, setup.psy_tone_dBsuppress ); vorbis_encode_peak_setup( hi.block[3].tone_peaklimit_setting, 3, setup.psy_tone_dBsuppress ); } /* noise bias setup */ vorbis_encode_noisebias_setup( hi.block[i0].noise_bias_setting, 0, setup.psy_noise_dBsuppress, setup.psy_noise_bias_impulse, setup.psy_noiseguards, (i0 == 0 ? hi.impulse_noisetune : 0.) ); vorbis_encode_noisebias_setup( hi.block[1].noise_bias_setting, 1, setup.psy_noise_dBsuppress, setup.psy_noise_bias_padding, setup.psy_noiseguards, 0. ); if( ! singleblock ) { vorbis_encode_noisebias_setup( hi.block[2].noise_bias_setting, 2, setup.psy_noise_dBsuppress, setup.psy_noise_bias_trans, setup.psy_noiseguards, 0. ); vorbis_encode_noisebias_setup( hi.block[3].noise_bias_setting, 3, setup.psy_noise_dBsuppress, setup.psy_noise_bias_long, setup.psy_noiseguards, 0. ); } vorbis_encode_ath_setup( 0 ); vorbis_encode_ath_setup( 1 ); if( ! singleblock ) { vorbis_encode_ath_setup( 2 ); vorbis_encode_ath_setup( 3 ); } vorbis_encode_map_n_res_setup( hi.base_setting, setup.maps ); /* set bitrate readonlies and management */ if( hi.bitrate_av > 0 ) { this.bitrate_nominal = hi.bitrate_av; } else { this.bitrate_nominal = (int)setting_to_approx_bitrate(); } this.bitrate_lower = hi.bitrate_min; this.bitrate_upper = hi.bitrate_max; if( hi.bitrate_av != 0 ) { this.bitrate_window = hi.bitrate_reservoir / hi.bitrate_av;// FIXME why double? } else { this.bitrate_window = 0;// FIXME why double 0.? } if( hi.managed ) { ci.bi.avg_rate = hi.bitrate_av; ci.bi.min_rate = hi.bitrate_min; ci.bi.max_rate = hi.bitrate_max; ci.bi.reservoir_bits = hi.bitrate_reservoir; ci.bi.reservoir_bias = hi.bitrate_reservoir_bias; ci.bi.slew_damp = hi.bitrate_av_damp; } return (0); } private final void vorbis_encode_setup_setting(final int nchannels, final int srate) { final Jcodec_setup_info ci = this.codec_setup; final Jhighlevel_encode_setup hi = ci.hi; final Jve_setup_data_template setup = hi.setup; this.version = 0; this.channels = nchannels; this.rate = srate; hi.impulse_block_p = true; hi.noise_normalize_p = true; final int is = (int)hi.base_setting; final double ds = hi.base_setting - is; final double ds1 = 1. - ds;// java hi.stereo_point_setting = hi.base_setting; if( ! hi.lowpass_altered ) { hi.lowpass_kHz = setup.psy_lowpass[is] * ds1 + setup.psy_lowpass[is + 1] * ds; } hi.ath_floating_dB = setup.psy_ath_float[is] * ds1 + setup.psy_ath_float[is + 1] * ds; hi.ath_absolute_dB = setup.psy_ath_abs[is] * ds1 + setup.psy_ath_abs[is + 1] * ds; hi.amplitude_track_dBpersec = -6.; hi.trigger_setting = hi.base_setting; final Jhighlevel_byblocktype[] block = hi.block;// java for( int i = 0; i < 4; i++ ) { final Jhighlevel_byblocktype bi = block[i];// java bi.tone_mask_setting = hi.base_setting; bi.tone_peaklimit_setting = hi.base_setting; bi.noise_bias_setting = hi.base_setting; bi.noise_compand_setting = hi.base_setting; } } /** * This function performs step-one of a three-step variable bitrate * (quality-based) encode setup. It functions similarly to the one-step setup * performed by {@link #vorbis_encode_init_vbr} but allows an application to * make further encode setup tweaks using {@link #vorbis_encode_ctl} before * finally calling {@link #vorbis_encode_setup_init} to complete the setup * process. *

* Before this function is called, the {@link Jvorbis_info} struct should be * initialized by using {@link #vorbis_info_init} from the libvorbis API. After * encoding, {@link #vorbis_info_clear} should be called. * * @param vi Pointer to an initialized vorbis_info struct. * @param nchannels The number of channels to be encoded. * @param srate The sampling rate of the source audio. * @param quality Desired quality level, currently from -0.1 to 1.0 (lo to hi). * * @return Zero for success, and negative values for failure. * * @retval 0 Success * @retval OV_EFAULT Internal logic fault; indicates a bug or heap/stack corruption. * @retval OV_EINVAL Invalid setup request, eg, out of range argument. * @retval OV_EIMPL Unimplemented mode; unable to comply with quality level request. */ public final int vorbis_encode_setup_vbr(final int nchannels, final int srate, float quality) { if( srate <= 0 ) { return Jcodec.OV_EINVAL; } final Jhighlevel_encode_setup hi = this.codec_setup.hi; quality += .0000001f; if( quality >= 1.f ) { quality = .9999f; } hi.req = quality; /*hi.setup = */get_setup_template( nchannels, srate, quality, false, hi ); if( hi.setup == null ) { return Jcodec.OV_EIMPL; } vorbis_encode_setup_setting( nchannels, srate ); hi.managed = false; hi.coupling_p = true; return 0; } /** * This is the primary function within libvorbisenc for setting up variable * bitrate ("quality" based) modes. *

* Before this function is called, the vorbis_info struct should be * initialized by using vorbis_info_init() from the libvorbis API. After * encoding, vorbis_info_clear() should be called. * * @param vi Pointer to an initialized vorbis_info struct. * @param nchannels The number of channels to be encoded. * @param srate The sampling rate of the source audio. * @param base_quality Desired quality level, currently from -0.1 to 1.0 (lo to hi). * * * @return Zero for success, or a negative number for failure. * * @retval 0 Success * @retval OV_EFAULT Internal logic fault; indicates a bug or heap/stack corruption. * @retval OV_EINVAL Invalid setup request, eg, out of range argument. * @retval OV_EIMPL Unimplemented mode; unable to comply with quality level request. */ public final int vorbis_encode_init_vbr(final int nchannels, final int srate, final float base_quality /* 0. to 1. */) { int ret = vorbis_encode_setup_vbr( nchannels, srate, base_quality ); if( ret != 0 ) { vorbis_info_clear(); return ret; } ret = vorbis_encode_setup_init(); if( ret != 0 ) { vorbis_info_clear(); } return (ret); } /** * This function performs step-one of a three-step bitrate-managed encode * setup. It functions similarly to the one-step setup performed by * {@link #vorbis_encode_init} but allows an application to make further encode setup * tweaks using {@link #vorbis_encode_ctl} before finally calling * {@link #vorbis_encode_setup_init} to complete the setup process. *

* Before this function is called, the {@link Jvorbis_info} struct should be * initialized by using vorbis_info_init() from the libvorbis API. After * encoding, vorbis_info_clear() should be called. *

* The max_bitrate, nominal_bitrate, and min_bitrate settings are used to set * constraints for the encoded file. This function uses these settings to * select the appropriate encoding mode and set it up. * * @param vi Pointer to an initialized vorbis_info struct. * @param nchannels The number of channels to be encoded. * @param srate The sampling rate of the source audio. * @param max_bitrate Desired maximum bitrate (limit). -1 indicates unset. * @param nominal_bitrate Desired average, or central, bitrate. -1 indicates unset. * @param min_bitrate Desired minimum bitrate. -1 indicates unset. * * @return Zero for success, and negative for failure. * * @retval 0 Success * @retval OV_EFAULT Internal logic fault; indicates a bug or heap/stack corruption. * @retval OV_EINVAL Invalid setup request, eg, out of range argument. * @retval OV_EIMPL Unimplemented mode; unable to comply with bitrate request. */ public final int vorbis_encode_setup_managed( final int nchannels, final int srate, final int max_bitrate, int nominal_bitrate, final int min_bitrate) { if( srate <= 0 ) { return Jcodec.OV_EINVAL; } final Jhighlevel_encode_setup hi = this.codec_setup.hi; final int tnominal = nominal_bitrate;// FIXME why double? if( nominal_bitrate <= 0 ) { if( max_bitrate > 0 ) { if( min_bitrate > 0 ) { nominal_bitrate = (max_bitrate + min_bitrate) >>> 1; } else { nominal_bitrate = (int)(max_bitrate * .875f); } } else { if( min_bitrate > 0 ) { nominal_bitrate = min_bitrate; } else { return (Jcodec.OV_EINVAL); } } } hi.req = nominal_bitrate; /*hi.setup = */get_setup_template( nchannels, srate, nominal_bitrate, true, hi ); if( hi.setup == null ) { return Jcodec.OV_EIMPL; } vorbis_encode_setup_setting( nchannels, srate ); /* initialize management with sane defaults */ hi.coupling_p = true; hi.managed = true; hi.bitrate_min = min_bitrate; hi.bitrate_max = max_bitrate; hi.bitrate_av = tnominal; hi.bitrate_av_damp = 1.5f; /* full range in no less than 1.5 second */ hi.bitrate_reservoir = nominal_bitrate << 1; hi.bitrate_reservoir_bias = .1; /* bias toward hoarding bits */ return (0); } /** * This is the primary function within libvorbisenc for setting up managed * bitrate modes. *

* Before this function is called, the {@link Jvorbis_info} * struct should be initialized by using vorbis_info_init() from the libvorbis * API. After encoding, vorbis_info_clear() should be called. *

* The max_bitrate, nominal_bitrate, and min_bitrate settings are used to set * constraints for the encoded file. This function uses these settings to * select the appropriate encoding mode and set it up. * * @param vi Pointer to an initialized {@link Jvorbis_info} struct. * @param nchannels The number of channels to be encoded. * @param srate The sampling rate of the source audio. * @param max_bitrate Desired maximum bitrate (limit). -1 indicates unset. * @param nominal_bitrate Desired average, or central, bitrate. -1 indicates unset. * @param min_bitrate Desired minimum bitrate. -1 indicates unset. * * @return Zero for success, and negative values for failure. * * @retval 0 Success. * @retval OV_EFAULT Internal logic fault; indicates a bug or heap/stack corruption. * @retval OV_EINVAL Invalid setup request, eg, out of range argument. * @retval OV_EIMPL Unimplemented mode; unable to comply with bitrate request. */ public final int vorbis_encode_init(final int nchannels, final int srate, final int max_bitrate, final int nominal_bitrate, final int min_bitrate) { int ret = vorbis_encode_setup_managed( nchannels, srate, max_bitrate, nominal_bitrate, min_bitrate ); if( ret != 0 ) { vorbis_info_clear(); return (ret); } ret = vorbis_encode_setup_init(); if( ret != 0 ) { vorbis_info_clear(); } return (ret); } /** * This function implements a generic interface to miscellaneous encoder * settings similar to the classic UNIX 'ioctl()' system call. Applications * may use vorbis_encode_ctl() to query or set bitrate management or quality * mode details by using one of several request arguments detailed below. * vorbis_encode_ctl() must be called after one of * vorbis_encode_setup_managed() or vorbis_encode_setup_vbr(). When used * to modify settings, {@link #vorbis_encode_ctl} must be called before * {@link #vorbis_encode_setup_init}. * * @param vi Pointer to an initialized vorbis_info struct. * * @param number Specifies the desired action; See {@link Jencctlcodes} * "the list of available requests". * * @param arg Object pointing to a data structure matching the request * argument. * * @retval 0 Success. Any further return information (such as the result of a * query) is placed into the storage pointed to by Object. * * @retval OV_EINVAL Invalid argument, or an attempt to modify a setting after * calling vorbis_encode_setup_init(). * * @retval OV_EIMPL Unimplemented or unknown request */ @SuppressWarnings("deprecation") public final int vorbis_encode_ctl(final int number, final Object arg) { //if( vi != null ) { final Jhighlevel_encode_setup hi = this.codec_setup.hi; final int setp = (number & 0xf); /* a read request has a low nibble of 0 */ if( setp != 0 && hi.set_in_stone != 0 ) { return (Jcodec.OV_EINVAL); } switch( number ) { /* now deprecated *****************/ case Jencctlcodes.OV_ECTL_RATEMANAGE_GET: { final Jovectl_ratemanage_arg ai = (Jovectl_ratemanage_arg)arg; ai.management_active = hi.managed; ai.bitrate_hard_window = ai.bitrate_av_window = (double)hi.bitrate_reservoir / this.rate; ai.bitrate_av_window_center = 1.; ai.bitrate_hard_min = hi.bitrate_min; ai.bitrate_hard_max = hi.bitrate_max; ai.bitrate_av_lo = hi.bitrate_av; ai.bitrate_av_hi = hi.bitrate_av; } return (0); /* now deprecated *****************/ case Jencctlcodes.OV_ECTL_RATEMANAGE_SET: { final Jovectl_ratemanage_arg ai = (Jovectl_ratemanage_arg)arg; if( ai == null ) { hi.managed = false; } else { hi.managed = ai.management_active; vorbis_encode_ctl( Jencctlcodes.OV_ECTL_RATEMANAGE_AVG, arg ); vorbis_encode_ctl( Jencctlcodes.OV_ECTL_RATEMANAGE_HARD, arg ); } } return 0; /* now deprecated *****************/ case Jencctlcodes.OV_ECTL_RATEMANAGE_AVG: { final Jovectl_ratemanage_arg ai = (Jovectl_ratemanage_arg)arg; if( ai == null ) { hi.bitrate_av = 0; } else {// FIXME is this a bug? (ai.bitrate_av_lo + ai.bitrate_av_hi) * .5; hi.bitrate_av = (ai.bitrate_av_lo + ai.bitrate_av_hi) >>> 1; } } return (0); /* now deprecated *****************/ case Jencctlcodes.OV_ECTL_RATEMANAGE_HARD: { final Jovectl_ratemanage_arg ai = (Jovectl_ratemanage_arg)arg; if( ai == null ) { hi.bitrate_min = 0; hi.bitrate_max = 0; } else { hi.bitrate_min = ai.bitrate_hard_min; hi.bitrate_max = ai.bitrate_hard_max; hi.bitrate_reservoir = (int)(ai.bitrate_hard_window * (hi.bitrate_max + hi.bitrate_min) * .5); } if( hi.bitrate_reservoir < 128 ) { hi.bitrate_reservoir = 128;// FIXME double 128. is this a bug? } } return (0); /* replacement ratemanage interface */ case Jencctlcodes.OV_ECTL_RATEMANAGE2_GET: { final Jovectl_ratemanage2_arg ai = (Jovectl_ratemanage2_arg)arg; if( ai == null ) { return Jcodec.OV_EINVAL; } ai.management_active = hi.managed; ai.bitrate_limit_min_kbps = hi.bitrate_min / 1000; ai.bitrate_limit_max_kbps = hi.bitrate_max / 1000; ai.bitrate_average_kbps = hi.bitrate_av / 1000; ai.bitrate_average_damping = hi.bitrate_av_damp; ai.bitrate_limit_reservoir_bits = hi.bitrate_reservoir; ai.bitrate_limit_reservoir_bias = hi.bitrate_reservoir_bias; } return (0); case Jencctlcodes.OV_ECTL_RATEMANAGE2_SET: { final Jovectl_ratemanage2_arg ai = (Jovectl_ratemanage2_arg)arg; if( ai == null ) { hi.managed = false; } else { /* sanity check; only catch invariant violations */ if( ai.bitrate_limit_min_kbps > 0 && ai.bitrate_average_kbps > 0 && ai.bitrate_limit_min_kbps > ai.bitrate_average_kbps ) { return Jcodec.OV_EINVAL; } if( ai.bitrate_limit_max_kbps > 0 && ai.bitrate_average_kbps > 0 && ai.bitrate_limit_max_kbps < ai.bitrate_average_kbps ) { return Jcodec.OV_EINVAL; } if( ai.bitrate_limit_min_kbps > 0 && ai.bitrate_limit_max_kbps > 0 && ai.bitrate_limit_min_kbps > ai.bitrate_limit_max_kbps ) { return Jcodec.OV_EINVAL; } if( ai.bitrate_average_damping <= 0. ) { return Jcodec.OV_EINVAL; } if( ai.bitrate_limit_reservoir_bits < 0 ) { return Jcodec.OV_EINVAL; } if( ai.bitrate_limit_reservoir_bias < 0. ) { return Jcodec.OV_EINVAL; } if( ai.bitrate_limit_reservoir_bias > 1. ) { return Jcodec.OV_EINVAL; } hi.managed = ai.management_active; hi.bitrate_min = ai.bitrate_limit_min_kbps * 1000; hi.bitrate_max = ai.bitrate_limit_max_kbps * 1000; hi.bitrate_av = ai.bitrate_average_kbps * 1000; hi.bitrate_av_damp = ai.bitrate_average_damping; hi.bitrate_reservoir = ai.bitrate_limit_reservoir_bits; hi.bitrate_reservoir_bias = ai.bitrate_limit_reservoir_bias; } } return 0; case Jencctlcodes.OV_ECTL_LOWPASS_GET: { final double[] farg = (double[])arg; farg[0] = hi.lowpass_kHz; } return (0); case Jencctlcodes.OV_ECTL_LOWPASS_SET: { final double[] farg = (double[])arg; hi.lowpass_kHz = farg[0]; if( hi.lowpass_kHz < 2. ) { hi.lowpass_kHz = 2.; } if( hi.lowpass_kHz > 99. ) { hi.lowpass_kHz = 99.; } hi.lowpass_altered = true; } return (0); case Jencctlcodes.OV_ECTL_IBLOCK_GET: { final double[] farg = (double[])arg; farg[0] = hi.impulse_noisetune; } return (0); case Jencctlcodes.OV_ECTL_IBLOCK_SET: { final double[] farg = (double[])arg; hi.impulse_noisetune = farg[0]; if( hi.impulse_noisetune > 0. ) { hi.impulse_noisetune = 0.; } if( hi.impulse_noisetune < -15. ) { hi.impulse_noisetune = -15.; } } return (0); case Jencctlcodes.OV_ECTL_COUPLING_GET: { final boolean[] iarg = (boolean[])arg; iarg[0] = hi.coupling_p; } return (0); case Jencctlcodes.OV_ECTL_COUPLING_SET: { final int[] iarg = (int[])arg; hi.coupling_p = (iarg[0] != 0); if( hi.setup == null ) { return Jcodec.OV_EIMPL; } /* Fetching a new template can alter the base_setting, which many other parameters are based on. Right now, the only parameter drawn from the base_setting that can be altered by an encctl is the lowpass, so that is explictly flagged to not be overwritten when we fetch a new template and recompute the dependant settings */ /*new_template = */get_setup_template( hi.coupling_p ? this.channels : -1, this.rate, hi.req, hi.managed, hi ); vorbis_encode_setup_setting( this.channels, this.rate ); } return (0); } return (Jcodec.OV_EIMPL); //} //return (Jcodec.OV_EINVAL); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy