www.pudn.com > jlayermp3midlet.rar > Mp3ToWav.java
/**
*
* Mp3ToWav DataSource
*
* JavaLayerME and MMAPI
*
*/
package javazoom.jlme.decoder;
import java.io.*;
import javax.microedition.media.*;
import javax.microedition.media.protocol.*;
import java.io.IOException;
/* Audio datasource for converting mp3 to wav
*/
public class Mp3ToWav extends DataSource implements SourceStream, Runnable {
// DataSource fields
String locator = null;
boolean connected = false;
String contentType = null;
// Comments field
private boolean comments;
// Defaults
private int sampleRate = 44100;
private int sampleSize = 16;
private int channels = 2;
private int endian = 0; // 0 for any, 1 for "little", 2 for "big"
private int signed = 1; // 0 for any, 1 for "signed", 2 for "unsigned"
// Productor
Thread prodThread;
public boolean stop=true;
private byte[] fifo;
private Object lock;
private int getAskFor=0;
private boolean locked=false;
private int f_g=0;
private int f_p=0;
private int f_size=0;
//private int FIFO_SIZE = 5000000;
private int FIFO_SIZE = 50000;
// Decoder JavaLayer
private Decoder decoder;
private Header header;
private BitStream bitstream;
private int dataLength=0;
private int lengthFrame;
private byte[] bArray;
private String file;
private Object lock2;
private boolean locked2=false;
// The WAVe header
private byte [] hdr = new byte[44];
private int hdrSize;
private int hdrOfs;
private static final String[] headerComments= {"Chunk RIFF","Chunk RIFF","Chunk RIFF","Chunk RIFF","Check Size (Length unbounded)","Check Size (Length unbounded)","Check Size (Length unbounded)","Check Size (Length unbounded)","FCC Type - WAVE","FCC Type - WAVE","FCC Type - WAVE","FCC Type - WAVE","Chunk Format - fmt","Chunk Format - fmt","Chunk Format - fmt","Chunk Format - fmt","Check Size","Check Size","Check Size","Check Size","1 means PCM","1 means PCM","Nb of Channels","Nb of Channels","Frequence byte/sec","Frequence byte/sec","Frequence byte/sec","Frequence byte/sec","Frequence byte/sec","Frequence byte/sec","Frequence byte/sec","Frequence byte/sec","Quantification - bytes","Quantification - bytes","Quantification - bits","Quantification - bits","Chunk Data","Chunk Data","Chunk Data","Chunk Data","Check Size","Check Size","Check Size","Check Size"};
/****************************************************************
* Runnable implementation
****************************************************************/
/**
* Main process loop driving the media flow.
*/
public void run() {
boolean endOfFile=false;
int toCopy=0;
int lap=0;
// First transfer the header
for (int i=0; i Synchro : DataSource locked");
locked2=true;
synchronized( lock2 ){
// here is where you'd check obj's state
while (locked2) {
try {
lock2.wait();
}
catch( InterruptedException e ){
if (comments) e.printStackTrace();
}
}
}
if (comments) System.out.println("-- Mp3Decoder Comments -------> Synchro : DataSource unlocked ");
}
lap++;
try
{
SampleBuffer output = (SampleBuffer)decoder.decodeFrame();
lengthFrame = output.size();
if (lengthFrame <= 0) {
if (comments) System.out.println("-- Mp3Decoder Comments -- Mp3ToWav DataSource -- End Of File");
endOfFile=true;break;
}
bArray=output.getBuffer();
if (f_size+lengthFramegetAskFor && locked==true) {
getAskFor=0;
locked=false;
synchronized(lock){
if (comments) System.out.println("-- Mp3Decoder Comments -------> Synchro : Notify buffer ready for reading");
lock.notifyAll();
}
}
}
else {
// buffer full
if (comments) System.out.println ("-- Mp3Decoder Comments -- CANT WRITE ANYMORE DATA -- Buffer Full -----");
}
if (comments) System.out.println("-- Mp3Decoder Comments -- WRITING -- lap "+lap+" -- buffering "+ f_size*100/FIFO_SIZE + " % -- " + f_size + "/" + FIFO_SIZE + " --" );
bitstream.closeFrame();
header = bitstream.readFrame();
} catch (Exception e) {
System.out.println("Mp3ToWav::run:Exception in thread prodthread");
}
}
if (comments) System.out.println("-- Mp3Decoder Comments -- End of the thread used by Mp3ToWav for writing in the buffer");
}
/****************************************************************
* DataSource implementation
****************************************************************/
public Mp3ToWav(String l, boolean c) {
super(l);
System.out.println("Enter Mp3ToWav Constructor>>" + l);
locator=l;
comments=c;
// Captures audio and wraps it into WAV content type
contentType = "audio/x-wav";
fifo=new byte[FIFO_SIZE];
lock=new Object();
lock2=new Object();
}
public void setLocator(String ml) {
locator = ml;
}
public String getLocator() {
return locator;
}
public String getContentType() {
if (!connected)
return null;
return contentType;
}
public void setContentType(String type) {
contentType = type;
}
public Control[] getControls() {
return new Control[0];
}
public Control getControl(String controlType) {
return null;
}
/**
* Parse the protocol part of the locator string.
*/
static public String getProtocol(String loc) {
String proto = "";
int idx = loc.indexOf(':');
if( idx != -1) {
proto = loc.substring(0,idx);
}
return proto;
}
/* return the numeric value for a property */
private int tryParam(String tok, String prop, int def) {
if (tok.startsWith(prop)) {
tok = tok.substring(prop.length(), tok.length());
if (prop.equals("signed=")) {
if (tok.equals("signed"))
return 1; // SIGNED
else if (tok.equals("unsigned"))
return 2; // UNSIGNED
} else if (prop.equals("endian=")) {
if (tok.equals("little"))
return 1; // LITTLE_ENDIAN
else if (tok.equals("big"))
return 2; // BIG_ENDIAN
} else {
try {
return Integer.parseInt(tok);
} catch (Exception e) {
}
}
}
return def;
}
/* Parse the URL, extract and validate the properties */
private boolean parseLocator() {
String loc = getLocator();
if (comments) System.out.println("-- Mp3Decoder Comments -- Parse Locator : " + loc);
if (!loc.endsWith(".mp3"))
return false;
return true;
}
public void connect() throws IOException {
System.out.println("Enter connect");
if (!parseLocator())
throw new IOException("Invalid locator");
// open the file and create the header
// throw an exception if the file has not been opened
// Open the file
try {
if (comments)
System.out.println("-- Mp3Decoder Comments -- Create decoder and connect the dataSource (Push the wav header)");
InputStream in = null;
in = getClass().getResourceAsStream(getLocator());
if(in == null)
{
System.out.println("无法获取music数据源!");
return;
}
else
{
bitstream = new BitStream(in);
header = bitstream.readFrame();
decoder = new Decoder(header,bitstream);
if (comments)
System.out.println("-- Mp3Decoder Comments -- WAV Stream mode : Frequency: "
+decoder.getOutputFrequency() + ",Channels: "
+ decoder.getOutputChannels());
}
System.gc();
}
catch (Exception e) {
if (comments)
System.out.println("Couldn't open audio input");
System.out.println("异常原因为:" + e.getMessage() + "/" + e.getClass());
throw new IOException("Couldn't open audio input");
}
// Generate the WAV header
createHeader(sampleRate, sampleSize, channels);
connected = true;
System.out.println("Generate the WAV header:okay");
// Start the playback loop.
prodThread = new Thread(this);
prodThread.start();
}
public void disconnect() {
//stop();
if (comments) System.out.println("-- Mp3Decoder Comments -- Mp3ToWav DataSource -- Disconnected");
locked2=false;
synchronized(lock2){
if (comments) System.out.println("-- Mp3Decoder Comments -------> Synchro : Notify DataSource");
lock2.notifyAll();
}
connected = false;
fifo=null;
System.gc();
}
public void start() throws IOException {
if (comments) System.out.println("-- Mp3Decoder Comments -- Mp3ToWav DataSource -- Started");
stopProd(false);
locked2=false;
synchronized(lock2){
if (comments) System.out.println("-- Mp3Decoder Comments -------> Synchro : Notify DataSource");
lock2.notifyAll();
}
}
public void stop() {
if (comments) System.out.println("-- Mp3Decoder Comments -- Mp3ToWav DataSource -- Stopped");
locked=false;
synchronized(lock){
if (comments) System.out.println("-- Mp3Decoder Comments -------> Synchro : Notify Buffer");
lock.notifyAll();
}
stopProd(true);
}
public SourceStream[] getStreams() {
return new SourceStream[] { this };
}
/****************************************************************
* SourceStream implementation
****************************************************************/
public ContentDescriptor getContentDescriptor() {
return new ContentDescriptor(getContentType());
}
public long getContentLength() {
return -1;
}
public int read(byte[] buffer, int offset, int length) throws IOException {
if (comments) System.out.println("-- Mp3Decoder Comments -- ASK FOR READING -- offset =>" + offset + ", length asked =>" + length );
int totalCopy=length;
while (f_size<=totalCopy && connected) {
// waiting
getAskFor=totalCopy;
locked=true;
if (comments) System.out.println("-- Mp3Decoder Comments -------> Synchro : Buffer Locked (empty)");
wait_get();
if (comments) System.out.println("-- Mp3Decoder Comments -------> Synchro : Buffer Unlocked (ready for reading)");
}
//if (f_size<=totalCopy) return 0;
if (comments) System.out.println("-- Mp3Decoder Comments -- READING -- " + totalCopy + " -- f_size : " + f_size);
if (f_g+totalCopy>> 8) & 0xFF);
hdr[hdrSize++] = (byte)((value >>> 16) & 0xFF);
hdr[hdrSize++] = (byte)((value >>> 24) & 0xFF);
}
// Write a short in LITTLE_ENDIAN
private void writeShort(int value) {
hdr[hdrSize++] = (byte)((value >> 0) & 0xFF);
hdr[hdrSize++] = (byte)((value >> 8) & 0xFF);
}
// Write the WAVe header into the hdr array
private void createHeader(int samplesPerSec,
int sampleSizeInBits,
int channels) {
System.out.println("Enter createHeader");
hdrSize = 0;
int avBytesPerSec = channels * samplesPerSec * (sampleSizeInBits / 8);
writeInt(0x46464952 /*RIFF*/);
writeInt(-1); // Length unbounded
writeInt(0x45564157 /*WAVE*/);
writeInt(0x20746D66 /*FMT*/); // Format Chunk
writeInt(16); // size of format chunk
writeShort(1); // wFormatTag ==> uncompressed
writeShort((short) channels);
writeInt(samplesPerSec);
writeInt(avBytesPerSec);
writeShort(channels * sampleSizeInBits / 8); // BlockAlign
writeShort(sampleSizeInBits);
writeInt(0x61746164 /*DATA*/); // Data chunk
writeInt(-1); // Length unbounded
}
/****************************************************************
* FIFO Methods
****************************************************************/
private void push(byte b){
f_size++;
fifo[f_p]=b;
f_p=(f_p+1)%FIFO_SIZE;
}
private byte get(){
wait_get();
f_size--;
//System.out.println("size : " + f_size);
int r= f_g;
f_g=(f_g+1)%FIFO_SIZE;
return fifo[r];
}
private void wait_get() {
synchronized( lock ){
// here is where you'd check obj's state
while (locked) {
try {
lock.wait();
}
catch( InterruptedException e ){
}
}
}
}
/****************************************************************
* Other Methods
****************************************************************/
public void startBuffering() {
stopProd(false);
locked2=false;
synchronized(lock2){
if (comments) System.out.println("-- Mp3Decoder Comments -------> Synchro : Notify DataSource");
lock2.notifyAll();
}
}
private void stopProd(boolean s) {
stop=s;
}
public void setConnected(boolean b) {
connected=b;
}
public void setComments(boolean b) {
comments=b;
}
public void setBufferSize(int i) {
FIFO_SIZE=i;
}
public int getBufferSize() {
return FIFO_SIZE;
}
public String getDetails() {
return "Layer(only III supported) : " + decoder.hd.layer_string()+ "\nBitrate index : " + decoder.hd.bitrate_string() + "\nFrequency : " + decoder.hd.sample_frequency_string() + "\nChannels : " +decoder.hd.mode_string();
}
}