/* $Id$
 *
 * Copyright (c) 1999 Xenonsoft Limited. All Rights Reserved.
 *
 * This software is protected by copyright. You are hereby notified from
 * now by reading this message. This software is also the confidential 
 * and proprietary information of Xenonsoft Limited.  ("Confidential
 * Information"). 
 *
 * This software is distributed under the Xenonsoft Public end user 
 * License ("XPeL"), where the machine-readable source code is provided 
 * under the "Open Source" model.
 * For more information, please read the file "LICENSE-XPL.txt" 
 */

// `AudioClipWave.java'

//
// Description:
//	Sound wave loaded from audio clip wave

//	  
// Author:
//      Peter Pilgrim 
//	Wed May 26 12:52:02 BST 1999
//	  
// RCS HEADER 
// 
// $Author$
// $Date$
// $Source$
// $Revision$    $State$    $Locker$
//
// ================================================================================
// History
//	  $Log$
// 
// 
//

package xenon.soundkit;

import java.io.*;
import java.util.*;

/**
 * A audio clip <b>sampled</b> waveform
 * 
 * @author Peter Pilgrim , Sun Aug 08 13:59:16 BST 1999
 * @version $Id$
 *
 */
public class AudioClipWave extends Wave
{
    /** private class object counter */
    protected static int	counter;

    /** the name of the audio clip */
    protected String		clipName;
    
    /** 
     * Constructs the sampled audio clip waveform from audio data file.
     *
     * @param file the <code>File</code>, which has the
     * Sun audio clip byte data (Mu-Law), which is converted to
     * linear data.
     *
     * @exception <code>IOException</code> if no I/O data could be read
     */
    public AudioClipWave( File file ) 
	throws IOException
    {
	super();

	this.clipName = file.getPath();

	FileInputStream fis=null;
	try {
	    fis = new FileInputStream( file );
	    byte [] clipData = loadAudioClipData( fis );
	    if ( clipData != null )
		convertMulawToLinear( clipData );
	    else
		throw new IOException("no audio clip data read.");
	}
	finally {
	    if (fis==null)
		try { fis.close(); } catch(IOException ioe) {}
	}
    }

    /**
     * Constructs the sampled audio clip waveform from the input stream
     * 
     * @param clipName is the name of the  audio clip
     * @param is the <code>InputStream</code>, which has the
     * Sun audio clip byte data (Mu-Law), which is convert to
     * linear data.
     *
     * @exception <code>IOException</code> if no I/O data could be read
     */
    public AudioClipWave( InputStream is )
	throws IOException
    {
	this( null, is );
    }
	    
    /**
     * Constructs the sampled audio clip waveform from an input stream
     * @param is the <code>InputStream</code>, which has the
     * Sun audio clip byte data (Mu-Law), which is convert to
     * linear data.
     *
     * @exception <code>IOException</code> if no I/O data could be read
     */
    public AudioClipWave( String clipName, InputStream is )
	throws IOException
    {
	super();

	if (clipName == null)
	    clipName = "<Untitled Clip"+(++counter)+">";
	this.clipName = clipName;

	byte [] clipData = loadAudioClipData( is );
	if ( clipData != null )
	    convertMulawToLinear( clipData );
	else
	    throw new IOException("no audio clip data read.");
    }

    /**
     * Constructs the sampled audio clip waveform from byte data
     * 
     * @param clip_data the Sun audio clip data (Mu-Law) which is convert to
     * linear data.
     */
    public AudioClipWave( byte [] clipData ) 
    {
	this( null, clipData );
    }
    
    /**
     * Constructs the sampled audio clip waveform from byte data
     * 
     * @param clipName is the name of the  audio clip
     * @param clip_data the Sun audio clip data (Mu-Law) which is convert to
     * linear data.
     */
    public AudioClipWave( String clipName, byte [] clipData ) 
    {
	super();

	if (clipName == null)
	    clipName = "<Untitled Clip"+(++counter)+">";
	this.clipName = clipName;
	convertMulawToLinear( clipData );
    }

    /** Load the audio clip data from the input stream as bytes */
    protected byte [] loadAudioClipData( InputStream is )
    {
	// System.out.println("loadAudioClipData("+is+")");
	
	byte [] clipData=null;
        BufferedInputStream bis=null;
        ByteArrayOutputStream out = new ByteArrayOutputStream();

        try {
            byte [] buffer = new byte[8192];
            bis = new BufferedInputStream( is );
            int total_bytes=0;
            int num_bytes;

	    // HACK: The next part is not really correct. Assuming the
	    // data is a Sun Audio File (*.au). I am skipping 32 bytes
	    // of the header, because I can't find the format
	    // documentation for it.
	    for ( int q=0; q<32; ++q ) bis.read();
	    
            while ( (num_bytes = bis.read( buffer )) > 0 ) {
                out.write( buffer, 0, num_bytes );
                total_bytes += num_bytes;
		// System.out.println( "num_bytes:"+num_bytes );
            }
	    // System.out.println( "total_bytes:"+total_bytes );
            clipData = out.toByteArray();
        }
        catch (IOException e) {
           clipData = null;
        }

	return (clipData);
    }
	
    /** 
     * Internal method that converts the Mu-law byte data to 
     * linear double bytes 
     */
    protected void convertMulawToLinear( byte[] clipData )
    {
	WAVELENGTH = clipData.length;
	wave = new double[WAVELENGTH];
	
	for (int j=0; j<WAVELENGTH; ++j) {
	    int value = clipData[j];
	    if (value<0)
		value=0;
	    else if (value>255) 
		value=255;
	    wave[j] = ((double)(SoundEngine.ulaw_to_linear[value] - 128.0))/128.0;
	}
    }
    
    /** generates the waveform ; this is no brainer for sampled 
     * audio clip data
     * Hence this method does nothing.
     */
    protected void generateWaveform() 
    {
    }

    /** Returns the waveform optimal rendering size, 
     * which is used by the rendering engine to generate 
     * the sound data. 
     */
    public int getOptimalLength()
    {
	return (32);
    }

    /** Sets the displayable name for the waveform */
    public void setDisplayName( String newName )
    {
	clipName = newName;
    }

    /** Returns displayable name for the waveform */
    public String getDisplayName()
    {
	return "(sampled) "+clipName;
    }
    
}

// fini
