/******************************************************************** * * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY * SOURCE IS * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * IN 'COPYING'. PLEASE READ THESE TERMS * BEFORE DISTRIBUTING. * * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 * by the Xiph.Org Foundation * http://www.xiph.org/ * * ********************************************************************/ package com.xenoage.zong.desktop.io.ogg.out; import java.io.FileInputStream; import java.io.IOException; import java.io.OutputStream; import org.xiph.libogg.ogg_packet; import org.xiph.libogg.ogg_page; import org.xiph.libogg.ogg_stream_state; import org.xiph.libvorbis.vorbis_block; import org.xiph.libvorbis.vorbis_comment; import org.xiph.libvorbis.vorbis_dsp_state; import org.xiph.libvorbis.vorbis_info; import org.xiph.libvorbis.vorbisenc; /** * Converts a WAVE file (.wav) to an Ogg Vorbis file (.ogg) stream. * * Based on code from the vorbis-java library, examples/VorbisEncoder.java. * * @author vorbis-java authors * @author Andreas Wenger */ public class VorbisEncoder { static vorbisenc encoder; static ogg_stream_state os; // take physical pages, weld into a logical stream of packets static ogg_page og; // one Ogg bitstream page. Vorbis packets are inside static ogg_packet op; // one raw packet of data for decode static vorbis_info vi; // struct that stores all the static vorbis bitstream settings static vorbis_comment vc; // struct that stores all the user comments static vorbis_dsp_state vd; // central working state for the packet->PCM decoder static vorbis_block vb; // local working space for packet->PCM decode static int READ = 1024; static byte[] readbuffer = new byte[READ * 4 + 44]; static int page_count = 0; static int block_count = 0; /** * Reads the given WAV file and converts it into OGG Vorbis. * The OGG data is written to the given stream, which is closed at the end. */ public static void convert(String wavFile, OutputStream oggStream) throws IOException { boolean eos = false; vi = new vorbis_info(); encoder = new vorbisenc(); if (!encoder.vorbis_encode_init_vbr(vi, 2, 44100, .3f)) { System.out.println("Failed to Initialize vorbisenc"); return; } vc = new vorbis_comment(); vc.vorbis_comment_add_tag("ENCODER", "Java Vorbis Encoder"); vd = new vorbis_dsp_state(); if (!vd.vorbis_analysis_init(vi)) { System.out.println("Failed to Initialize vorbis_dsp_state"); return; } vb = new vorbis_block(vd); java.util.Random generator = new java.util.Random(); // need to randomize seed os = new ogg_stream_state(generator.nextInt(256)); //System.out.print("Writing header."); ogg_packet header = new ogg_packet(); ogg_packet header_comm = new ogg_packet(); ogg_packet header_code = new ogg_packet(); vd.vorbis_analysis_headerout(vc, header, header_comm, header_code); os.ogg_stream_packetin(header); // automatically placed in its own page os.ogg_stream_packetin(header_comm); os.ogg_stream_packetin(header_code); og = new ogg_page(); op = new ogg_packet(); while (!eos) { if (!os.ogg_stream_flush(og)) break; oggStream.write(og.header, 0, og.header_len); oggStream.write(og.body, 0, og.body_len); //System.out.print("."); } //System.out.print("Done.\n"); FileInputStream fin = new FileInputStream(wavFile); //System.out.print("Encoding."); while (!eos) { int i; int bytes = fin.read(readbuffer, 0, READ * 4); // stereo hardwired here if (bytes == 0) { // end of file. this can be done implicitly in the mainline, // but it's easier to see here in non-clever fashion. // Tell the library we're at end of stream so that it can handle // the last frame and mark end of stream in the output properly vd.vorbis_analysis_wrote(0); } else { // data to encode // expose the buffer to submit data float[][] buffer = vd.vorbis_analysis_buffer(READ); // uninterleave samples for (i = 0; i < bytes / 4; i++) { buffer[0][vd.pcm_current + i] = ((readbuffer[i * 4 + 1] << 8) | (0x00ff & (int) readbuffer[i * 4])) / 32768.f; buffer[1][vd.pcm_current + i] = ((readbuffer[i * 4 + 3] << 8) | (0x00ff & (int) readbuffer[i * 4 + 2])) / 32768.f; } // tell the library how much we actually submitted vd.vorbis_analysis_wrote(i); } // vorbis does some data preanalysis, then divvies up blocks for more involved // (potentially parallel) processing. Get a single block for encoding now while (vb.vorbis_analysis_blockout(vd)) { // analysis, assume we want to use bitrate management vb.vorbis_analysis(null); vb.vorbis_bitrate_addblock(); while (vd.vorbis_bitrate_flushpacket(op)) { // weld the packet into the bitstream os.ogg_stream_packetin(op); // write out pages (if any) while (!eos) { if (!os.ogg_stream_pageout(og)) { break; } oggStream.write(og.header, 0, og.header_len); oggStream.write(og.body, 0, og.body_len); // this could be set above, but for illustrative purposes, I do // it here (to show that vorbis does know where the stream ends) if (og.ogg_page_eos() > 0) eos = true; } } } //System.out.print("."); } fin.close(); oggStream.close(); //System.out.print("Done.\n"); } }