Package com.tulskiy.musique.audio.formats.ogg

Source Code of com.tulskiy.musique.audio.formats.ogg.VorbisEncoder

/*
* Copyright (c) 2008, 2009, 2010 Denis Tulskiy
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with this work.  If not, see <http://www.gnu.org/licenses/>.
*/

package com.tulskiy.musique.audio.formats.ogg;

import com.tulskiy.musique.audio.Encoder;
import com.tulskiy.musique.system.configuration.Configuration;

import org.xiph.libogg.ogg_packet;
import org.xiph.libogg.ogg_page;
import org.xiph.libogg.ogg_stream_state;
import org.xiph.libvorbis.*;

import javax.sound.sampled.AudioFormat;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.logging.Level;

/**
* Based on sample VorbisEncoder from vorbis-java
* <p/>
* Author: Denis Tulskiy
* Date: Jul 26, 2010
*/
public class VorbisEncoder implements Encoder {
    private ogg_stream_state os;    // take physical pages, weld into a logical stream of packets

    private ogg_page og;    // one Ogg bitstream page.  Vorbis packets are inside
    private ogg_packet op;    // one raw packet of data for decode

    private vorbis_dsp_state vd;    // central working state for the packet->PCM decoder
    private vorbis_block vb;    // local working space for packet->PCM decode
    private FileOutputStream output;
    private static final float DEFAULT_BITRATE = 0.3f;

    @Override
    public boolean open(File outputFile, AudioFormat fmt, Configuration options) {
        vorbis_info vi = new vorbis_info();
        vorbisenc encoder = new vorbisenc();

        float quality = DEFAULT_BITRATE;
        if (options != null) {
            quality = options.getFloat("encoder.vorbis.quality", DEFAULT_BITRATE);
        }
        logger.log(Level.INFO, "Starting encoding with {0} channels, {1} Hz, quality: {2}",
                new Object[]{fmt.getChannels(), fmt.getSampleRate(), quality});
        if (!encoder.vorbis_encode_init_vbr(vi, fmt.getChannels(), (int) fmt.getSampleRate(), quality)) {
            logger.warning("Failed to Initialize vorbisenc");
            return false;
        }

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

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

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

        try {
            output = new FileOutputStream(outputFile);

            if (!os.ogg_stream_flush(og))
                return false;

            output.write(og.header, 0, og.header_len);
            output.write(og.body, 0, og.body_len);
            return true;
        } catch (Exception ignored) {
        }

        return false;
    }

    @Override
    public void encode(byte[] buf, int len) {
        try {
            int i;
            // expose the buffer to submit data
            float[][] buffer = vd.vorbis_analysis_buffer(len / 4);
            // uninterleave samples
            for (i = 0; i < len / 4; i++) {
                buffer[0][vd.pcm_current + i] = ((buf[i * 4 + 1] << 8) | (0x00ff & (int) buf[i * 4])) / 32768.f;
                buffer[1][vd.pcm_current + i] = ((buf[i * 4 + 3] << 8) | (0x00ff & (int) buf[i * 4 + 2])) / 32768.f;
            }

            // tell the library how much we actually submitted
            vd.vorbis_analysis_wrote(i);

            analyze();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void analyze() throws IOException {
        // vorbis does some data preanalysis, then divvies up blocks for more involved
        // (potentially parallel) processing.  Get a single block for encoding now
        boolean eos = false;

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

                    output.write(og.header, 0, og.header_len);
                    output.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;
                }
            }
        }
    }

    @Override
    public void close() {
        try {
            if (vd != null) {
                vd.vorbis_analysis_wrote(0);
                analyze();
            }
            if (output != null)
                output.close();
        } catch (Exception ignored) {
        }
    }
}
TOP

Related Classes of com.tulskiy.musique.audio.formats.ogg.VorbisEncoder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.