Copyright 2011-01-06 Werner Randelshofer

ch.randelshofer.media.eightsvx
Class EightSVXAudioClip

java.lang.Object
  extended by ch.randelshofer.media.eightsvx.EightSVXAudioClip
All Implemented Interfaces:
LoopableAudioClip, java.applet.AudioClip

public class EightSVXAudioClip
extends java.lang.Object
implements LoopableAudioClip

Represents an audio sample of type IFF 8SVX.

Supported audio formats:
8 bit linear and fibonacci encoded data samples.
All sample rates
Stereo and Mono

Unsupported features:
Attack and Release information is ignored.
Multi octave samples are not handled.

Known Issues
This class has been implemented with JDK 1.1 in mind. JDK 1.1 does not have a public API for Sound. This class will thus work only on a small number of Java VMS.
Poor sound qualitiy: All data is being converted to U-Law 8000 Hertz, since this is the only kind of audio data that JDK 1.1 supports (As far as I know).
Stereo sound is converted to mono. As far as I know there is now stereo support built in JDK 1.1.

Version:
1.1 2003-04-05 Revised.
1.0 1999-10-19
Author:
Werner Randelshofer, Hausmatt 10, CH-6405 Immensee, Switzerland

Field Summary
static int LEFT
           
static int RIGHT
           
static int S_CMP_FIB_DELTA
           
static int S_CMP_NONE
           
static int STEREO
           
 
Fields inherited from interface ch.randelshofer.media.eightsvx.LoopableAudioClip
LOOP_CONTINUOUSLY
 
Constructor Summary
EightSVXAudioClip()
           
 
Method Summary
static double computeStereoVolumeCorrection(byte[] stereo)
          This finds the volume correction needed when converting this stereo sample to mono.
 LoopableAudioClip createAudioClip()
           
 LoopableAudioClip createAudioClip(int sampleRate, int volume, float pan)
           
 LoopableAudioClip createJDK10AudioClip(int sampleRate)
           
 LoopableAudioClip createJDK13AudioClip(int sampleRate, int volume, float pan)
           
 byte[] get8SVXBody()
           
protected  java.lang.String getAuthor()
           
protected  java.lang.String getCopyright()
           
 int getCtOctave()
           
protected  java.lang.String getName()
           
 long getOneShotHiSamples()
           
protected  java.lang.String getRemark()
           
 long getRepeatHiSamples()
           
 int getSampleRate()
           
 long getSamplesPerHiCycle()
           
 long getSampleType()
           
 int getSCompression()
           
 int getVolume()
           
static byte[] linear16ToULaw(int[] linear16)
          Converts a buffer of signed 8bit samples to uLaw.
static byte[] linear8StereoToMono(byte[] stereo, double volumeCorrection)
          This converts a stereo sample to mono.
static byte[] linear8ToULaw(byte[] linear8)
          Halfband lowpass.
 void loop()
           
 void loop(int count)
          Starts looping playback from the current position.
 void play()
           
 void prepare()
          Make this clip ready for playback.
static byte[] resample(byte[] input, int inputSampleRate, int outputSampleRate)
          Resamples audio data to match the given sample rate and applies a lowpass filter if necessary.
 void set8SVXBody(byte[] value)
           
protected  void setAuthor(java.lang.String value)
           
protected  void setCopyright(java.lang.String value)
           
 void setCtOctave(int value)
           
protected  void setName(java.lang.String value)
           
 void setOneShotHiSamples(long value)
           
protected  void setRemark(java.lang.String value)
           
 void setRepeatHiSamples(long value)
           
 void setSampleRate(int value)
           
 void setSamplesPerHiCycle(long value)
           
 void setSampleType(int value)
           
 void setSCompression(int value)
           
 void setVolume(int value)
           
 void stop()
           
 java.lang.String toString()
           
static byte[] unpackFibonacciDeltaCompression(byte[] source)
          Unpack Fibonacci-delta encoded data from n byte source buffer into 2*(n-2) byte dest buffer.
static void writeSunAudioHeader(java.io.OutputStream outfile, int dataSize, int sampleRate, int sampleType)
          Write a "standard" sun header.
static void wrulong(java.io.OutputStream outfile, int ulong)
          Write an unsigned long (Motorola 68000 CPU format).
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

S_CMP_NONE

public static final int S_CMP_NONE
See Also:
Constant Field Values

S_CMP_FIB_DELTA

public static final int S_CMP_FIB_DELTA
See Also:
Constant Field Values

RIGHT

public static final int RIGHT
See Also:
Constant Field Values

LEFT

public static final int LEFT
See Also:
Constant Field Values

STEREO

public static final int STEREO
See Also:
Constant Field Values
Constructor Detail

EightSVXAudioClip

public EightSVXAudioClip()
Method Detail

setName

protected void setName(java.lang.String value)

getName

protected java.lang.String getName()

setAuthor

protected void setAuthor(java.lang.String value)

getAuthor

protected java.lang.String getAuthor()

setCopyright

protected void setCopyright(java.lang.String value)

getCopyright

protected java.lang.String getCopyright()

setRemark

protected void setRemark(java.lang.String value)

getRemark

protected java.lang.String getRemark()

set8SVXBody

public void set8SVXBody(byte[] value)

get8SVXBody

public byte[] get8SVXBody()

setOneShotHiSamples

public void setOneShotHiSamples(long value)

setRepeatHiSamples

public void setRepeatHiSamples(long value)

setSamplesPerHiCycle

public void setSamplesPerHiCycle(long value)

setSampleType

public void setSampleType(int value)

setSampleRate

public void setSampleRate(int value)

setCtOctave

public void setCtOctave(int value)

setSCompression

public void setSCompression(int value)

setVolume

public void setVolume(int value)

getOneShotHiSamples

public long getOneShotHiSamples()

getRepeatHiSamples

public long getRepeatHiSamples()

getSamplesPerHiCycle

public long getSamplesPerHiCycle()

getSampleType

public long getSampleType()

getSampleRate

public int getSampleRate()

getCtOctave

public int getCtOctave()

getVolume

public int getVolume()

getSCompression

public int getSCompression()

toString

public java.lang.String toString()
Overrides:
toString in class java.lang.Object

createAudioClip

public LoopableAudioClip createAudioClip()

createAudioClip

public LoopableAudioClip createAudioClip(int sampleRate,
                                         int volume,
                                         float pan)

createJDK13AudioClip

public LoopableAudioClip createJDK13AudioClip(int sampleRate,
                                              int volume,
                                              float pan)

createJDK10AudioClip

public LoopableAudioClip createJDK10AudioClip(int sampleRate)

play

public void play()
Specified by:
play in interface java.applet.AudioClip

loop

public void loop()
Specified by:
loop in interface java.applet.AudioClip

stop

public void stop()
Specified by:
stop in interface java.applet.AudioClip

prepare

public void prepare()
Make this clip ready for playback.


computeStereoVolumeCorrection

public static double computeStereoVolumeCorrection(byte[] stereo)
This finds the volume correction needed when converting this stereo sample to mono.

Parameters:
stereo - Stereo data linear 8. The first half of the array contains the sound for the left speaker, the second half the sound for the right speaker.
Returns:
volumeCorrection Combining the two channels into one increases the sound volume. This can exceed the maximum volume that can be represented by the linear8 sample model. To avoid this, the volume must be corrected to fit into the sample model.

linear8StereoToMono

public static byte[] linear8StereoToMono(byte[] stereo,
                                         double volumeCorrection)
This converts a stereo sample to mono.

Parameters:
stereo - Stereo data linear 8. The first half of the array contains the sound for the left speaker, the second half the sound for the right speaker.
volumeCorrection - Combining the two channels into one increases the sound volume. This can exceed the maximum volume that can be represented by the linear8 sample model. To avoid this, the volume must be corrected to fit into the sample model.

resample

public static byte[] resample(byte[] input,
                              int inputSampleRate,
                              int outputSampleRate)
Resamples audio data to match the given sample rate and applies a lowpass filter if necessary.

Parameters:
input - Linear8 encoded audio data.
inputSampleRate - The sample rate of the input data
outputSampleRate - The sample rate of the output data.
Returns:
Linear8 encoded audio data.

linear8ToULaw

public static byte[] linear8ToULaw(byte[] linear8)
Halfband lowpass. / public static byte[] halfbandLowpass(byte[] input) { /* Algorithm taken from "Yehar's digital sound processing tutorial for the braindead!" version 2001.05.02 http://www.student.oulu.fi/~oniemita/DSP/DSPSTUFF.TXT Halfband lowpass *** b1 = 0.641339 b10 = -0.0227141 b2 = -3.02936 b3 = 1.65298 a0a12 = 0.008097 b4 = -3.4186 a1a11 = 0.048141 b5 = 1.50021 a2a10 = 0.159244 b6 = -1.73656 a3a9 = 0.365604 b7 = 0.554138 a4a8 = 0.636780 b8 = -0.371742 a5a7 = 0.876793 b9 = 0.0671787 a6 = 0.973529 output(t) = a0a12*(input(t ) + input(t-12)) + a1a11*(input(t-1) + input(t-11)) + a2a10*(input(t-2) + input(t-10)) + a3a9* (input(t-3) + input(t-9 )) + a4a8* (input(t-4) + input(t-8 )) + a5a7* (input(t-5) + input(t-7 )) + a6*input(t-6) + b1*output(t-1) + b2*output(t-2) + b3*output(t-3) + b4*output(t-4) + b5*output(t-5) + b6*output(t-6) + b7*output(t-7) + b8*output(t-8) + b9*output(t-9) + b10*output(t-10) / double b1 = 0.641339, b10 = -0.0227141, b2 = -3.02936, b3 = 1.65298, a0a12 = 0.008097, b4 = -3.4186 , a1a11 = 0.048141, b5 = 1.50021, a2a10 = 0.159244, b6 = -1.73656, a3a9 = 0.365604, b7 = 0.554138, a4a8 = 0.636780, b8 = -0.371742 , a5a7 = 0.876793, b9 = 0.0671787 , a6 = 0.973529; // Create the output array byte[] output = new byte[input.length]; for (int t=12; t < input.length; t++) { output[t] = (byte) ( a0a12*(input[t] + input[t-12]) + a1a11*(input[t-1] + input[t-11]) + a2a10*(input[t-2] + input[t-10]) + a3a9* (input[t-3] + input[t-9 ]) + a4a8* (input[t-4] + input[t-8 ]) + a5a7* (input[t-5] + input[t-7 ]) + a6*input[t-6] + b1*output[t-1] + b2*output[t-2] + b3*output[t-3] + b4*output[t-4] + b5*output[t-5] + b6*output[t-6] + b7*output[t-7] + b8*output[t-8] + b9*output[t-9] + b10*output[t-10] ); } return output; } /** Converts a buffer of signed 8bit samples to uLaw. The uLaw bytes overwrite the original 8 bit values. The first byte-offset of the uLaw bytes is byteOffset. It will be written sampleCount bytes.


linear16ToULaw

public static byte[] linear16ToULaw(int[] linear16)
Converts a buffer of signed 8bit samples to uLaw. The uLaw bytes overwrite the original 8 bit values. The first byte-offset of the uLaw bytes is byteOffset. It will be written sampleCount bytes.


unpackFibonacciDeltaCompression

public static byte[] unpackFibonacciDeltaCompression(byte[] source)
Unpack Fibonacci-delta encoded data from n byte source buffer into 2*(n-2) byte dest buffer. Source buffer has a pad byte, an 8-bit initial value, followed by n bytes comprising 2*(n) 4-bit encoded samples.


writeSunAudioHeader

public static void writeSunAudioHeader(java.io.OutputStream outfile,
                                       int dataSize,
                                       int sampleRate,
                                       int sampleType)
                                throws java.io.IOException
Write a "standard" sun header.

Parameters:
sampleType - Specify STEREO, LEFT or RIGHT.
Throws:
java.io.IOException

wrulong

public static void wrulong(java.io.OutputStream outfile,
                           int ulong)
                    throws java.io.IOException
Write an unsigned long (Motorola 68000 CPU format).

Throws:
java.io.IOException

loop

public void loop(int count)
Starts looping playback from the current position. Playback will continue to the loop's end point, then loop back to the loop start point count times, and finally continue playback to the end of the clip.

If the current position when this method is invoked is greater than the loop end point, playback simply continues to the end of the clip without looping.

A count value of 0 indicates that any current looping should cease and playback should continue to the end of the clip. The behavior is undefined when this method is invoked with any other value during a loop operation.

If playback is stopped during looping, the current loop status is cleared; the behavior of subsequent loop and start requests is not affected by an interrupted loop operation.

Specified by:
loop in interface LoopableAudioClip
Parameters:
count - the number of times playback should loop back from the loop's end position to the loop's start position, or LoopableAudioClip.LOOP_CONTINUOUSLY to indicate that looping should continue until interrupted

Copyright 2011-01-06 Werner Randelshofer