当前位置: 编程技术>移动开发
本页文章导读:
▪wave混音的兑现(1) wave混音的实现(1)
先看关于wav文件的头信息下面是封装好的一个辅助类。用于生成头部信息。package example.audiotest;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
/**
*
* @author cninjazh.........
▪ stringbuffer 跟stringbuilder的区别 stringbuffer 和stringbuilder的区别
虽然都知道String和它们的区别,但是我还有很多朋友说不清 stringbuffer 和stringbuilder的区别,很惭愧,我以前也说不清楚,今天发给大家共同学习 java.........
▪ wave混音的兑现(2) wave混音的实现(2)
关于混音算法,参考的是http://jacky-zhang.iteye.com/blog/766053,下面是具体的实现逻辑package example.audio;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io..........
[1]wave混音的兑现(1)
来源: 互联网 发布时间: 2014-02-18
wave混音的实现(1)
先看关于wav文件的头信息
下面是封装好的一个辅助类。用于生成头部信息。
先看关于wav文件的头信息
下面是封装好的一个辅助类。用于生成头部信息。
package example.audiotest; import java.io.ByteArrayOutputStream; import java.io.IOException; /** * * @author cninjazh * WavHeader辅助类。用于生成头部信息。 * WAV标准,头部应该是44字节 */ public class WaveHeader { public final char fileID[] = { 'R', 'I', 'F', 'F' }; public int fileLength; public char wavTag[] = { 'W', 'A', 'V', 'E' }; public char fmtHdrID[] = { 'f', 'm', 't', ' ' }; public int fmtHdrLeth; public short formatTag; public short channels; public int samplesPerSec; public int avgBytesPerSec; public short blockAlign; public short bitsPerSample; public char dataHdrID[] = { 'd', 'a', 't', 'a' }; public int dataHdrLeth; /* * pre-define wave header for 256kbps, 16bit, 16kHz, 1(mono), pcm * 填入参数,比特率等等。这里用的是16位单声道 16000Hz * fileLength = 内容的大小(dataSize) + 头部字段的大小(不包括前面4字节的标识符RIFF以及fileLength本身的4字节) * avgBytesPerSec = 8bit/16bit、11kHz/16kHz的WAV流进行传输(最大流量为16*16=256kbps=32KB/s) */ public WaveHeader(int dataSize) { fileLength = dataSize + (44 - 8); fmtHdrLeth = 16; bitsPerSample = 16; channels = 1; formatTag = 0x0001; samplesPerSec = 16000; blockAlign = (short) (channels * bitsPerSample / 8); avgBytesPerSec = blockAlign * samplesPerSec; dataHdrLeth = dataSize; } public WaveHeader(int dataSize, short bitsPerSample, int samplesPerSec) { fileLength = dataSize + (44 - 8); fmtHdrLeth = 16; this.bitsPerSample = bitsPerSample; channels = 1; formatTag = 0x0001; this.samplesPerSec = samplesPerSec; blockAlign = (short) (channels * bitsPerSample / 8); avgBytesPerSec = blockAlign * samplesPerSec; dataHdrLeth = dataSize; } public byte[] getHeader() throws IOException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); /* * ①RIFF WAVE Chunk ================================== | |所占字节数| 具体内容 | ================================== | ID | 4 Bytes | 'RIFF' | ---------------------------------- | Size | 4 Bytes | | ---------------------------------- | Type | 4 Bytes | 'WAVE' | ---------------------------------- */ WriteChar(bos, fileID);//以RIFF作为标识 WriteInt(bos, fileLength);//size,该size的大小是整个WAVE文件大小减去8个字节 WriteChar(bos, wavTag);//Type字段,为"WAVE"表示是Wav文件 /* * ②Format Chunk ==================================================================== | | 字节数 | 具体内容 | ==================================================================== | ID | 4 Bytes | 'fmt ' | -------------------------------- | Size | 4 Bytes | 数值为16或18,18则最后又附加信息 | -------------------------------- ---- | FormatTag | 2 Bytes | 编码方式,一般为0x0001 | | -------------------------------- | | Channels | 2 Bytes | 声道数目,1--单声道;2--双声道 | | -------------------------------- | | SamplesPerSec | 4 Bytes | 采样频率 | | -------------------------------- | | AvgBytesPerSec| 4 Bytes | 每秒所需字节数 | |===> WAVE_FORMAT -------------------------------- | | BlockAlign | 2 Bytes | 数据块对齐单位(每个采样需要的字节数) | | -------------------------------- | | BitsPerSample | 2 Bytes | 每个采样需要的bit数 | | -------------------------------- | | | 2 Bytes | 附加信息(可选,通过Size来判断有无) | | -------------------------------- ---- */ WriteChar(bos, fmtHdrID);//以"fmt "作为标识 WriteInt(bos, fmtHdrLeth);//一般长度为16个字节,如果是18个字节则有附加信息,写在最后两个字节上 WriteShort(bos, formatTag); WriteShort(bos, channels); WriteInt(bos, samplesPerSec); WriteInt(bos, avgBytesPerSec); WriteShort(bos, blockAlign); WriteShort(bos, bitsPerSample); WriteChar(bos, dataHdrID); WriteInt(bos, dataHdrLeth); bos.flush(); byte[] r = bos.toByteArray(); bos.close(); return r; } private void WriteShort(ByteArrayOutputStream bos, int s) throws IOException { byte[] mybyte = new byte[2]; mybyte[1] = (byte) ((s << 16) >> 24); mybyte[0] = (byte) ((s << 24) >> 24); bos.write(mybyte); } private void WriteInt(ByteArrayOutputStream bos, int n) throws IOException { byte[] buf = new byte[4]; buf[3] = (byte) (n >> 24); buf[2] = (byte) ((n << 8) >> 24); buf[1] = (byte) ((n << 16) >> 24); buf[0] = (byte) ((n << 24) >> 24); bos.write(buf); } private void WriteChar(ByteArrayOutputStream bos, char[] id) { for (int i = 0; i < id.length; i++) { char c = id[i]; bos.write(c); } } }
[2] stringbuffer 跟stringbuilder的区别
来源: 互联网 发布时间: 2014-02-18
stringbuffer 和stringbuilder的区别
虽然都知道String和它们的区别,但是我还有很多朋友说不清 stringbuffer 和stringbuilder的区别,很惭愧,我以前也说不清楚,今天发给大家共同学习
java.lang.StringBuffer线程安全的可变字符序列。一个类似于 String 的字符串缓冲区,但不能修改。虽然在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。
可将字符串缓冲区安全地用于多个线程。可以在必要时对这些方法进行同步,因此任意特定实例上的所有操作就好像是以串行顺序发生的,该顺序与所涉及的每个线程进行的方法调用顺序一致。
StringBuffer 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串缓冲区中。append 方法始终将这些字符添加到缓冲区的末端;而 insert 方法则在指定的点添加字符。
例如,如果 z 引用一个当前内容是"start"的字符串缓冲区对象,则此方法调用 z.append("le") 会使字符串缓冲区包含"startle",而 z.insert(4, "le") 将更改字符串缓冲区,使之包含"starlet"。
通常,如果 sb 引用 StringBuilder 的一个实例,则 sb.append(x) 和 sb.insert(sb.length(), x) 具有相同的效果。
只要发生有关源序列(如在源序列中追加或插入)的操作,该类就只在执行此操作的字符串缓冲区上而不是在源上实现同步。
每个字符串缓冲区都有一定的容量。只要字符串缓冲区所包含的字符序列的长度没有超出此容量,就无需分配新的内部缓冲区数组。如果内部缓冲区溢出,则此容量自动增大。从 JDK 5 开始,为该类补充了一个单个线程使用的等价类,即 StringBuilder。与该类相比,通常应该优先使用 StringBuilder 类,因为它支持所有相同的操作,但由于它不执行同步,所以速度更快。
java.lang.StringBuilder一个可变的字符序列。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。如果可能,建议优先采用该类,因为在大多数实现中,它比 StringBuffer 要快。
在 StringBuilder 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串生成器中。append 方法始终将这些字符添加到生成器的末端;而 insert 方法则在指定的点添加字符。
例如,如果 z 引用一个当前内容为"start"的字符串生成器对象,则该方法调用 z.append("le") 将使字符串生成器包含"startle",而 z.insert(4, "le") 将更改字符串生成器,使之包含"starlet"。
通常,如果 sb 引用 StringBuilder 的实例,则 sb.append(x) 和 sb.insert(sb.length(), x) 具有相同的效果。 每个字符串生成器都有一定的容量。只要字符串生成器所包含的字符序列的长度没有超出此容量,就无需分配新的内部缓冲区。如果内部缓冲区溢出,则此容量自动增大。
将 StringBuilder 的实例用于多个线程是不安全的。如果需要这样的同步,则建议使用 StringBuffer。
虽然都知道String和它们的区别,但是我还有很多朋友说不清 stringbuffer 和stringbuilder的区别,很惭愧,我以前也说不清楚,今天发给大家共同学习
java.lang.StringBuffer线程安全的可变字符序列。一个类似于 String 的字符串缓冲区,但不能修改。虽然在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。
可将字符串缓冲区安全地用于多个线程。可以在必要时对这些方法进行同步,因此任意特定实例上的所有操作就好像是以串行顺序发生的,该顺序与所涉及的每个线程进行的方法调用顺序一致。
StringBuffer 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串缓冲区中。append 方法始终将这些字符添加到缓冲区的末端;而 insert 方法则在指定的点添加字符。
例如,如果 z 引用一个当前内容是"start"的字符串缓冲区对象,则此方法调用 z.append("le") 会使字符串缓冲区包含"startle",而 z.insert(4, "le") 将更改字符串缓冲区,使之包含"starlet"。
通常,如果 sb 引用 StringBuilder 的一个实例,则 sb.append(x) 和 sb.insert(sb.length(), x) 具有相同的效果。
只要发生有关源序列(如在源序列中追加或插入)的操作,该类就只在执行此操作的字符串缓冲区上而不是在源上实现同步。
每个字符串缓冲区都有一定的容量。只要字符串缓冲区所包含的字符序列的长度没有超出此容量,就无需分配新的内部缓冲区数组。如果内部缓冲区溢出,则此容量自动增大。从 JDK 5 开始,为该类补充了一个单个线程使用的等价类,即 StringBuilder。与该类相比,通常应该优先使用 StringBuilder 类,因为它支持所有相同的操作,但由于它不执行同步,所以速度更快。
java.lang.StringBuilder一个可变的字符序列。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。如果可能,建议优先采用该类,因为在大多数实现中,它比 StringBuffer 要快。
在 StringBuilder 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串生成器中。append 方法始终将这些字符添加到生成器的末端;而 insert 方法则在指定的点添加字符。
例如,如果 z 引用一个当前内容为"start"的字符串生成器对象,则该方法调用 z.append("le") 将使字符串生成器包含"startle",而 z.insert(4, "le") 将更改字符串生成器,使之包含"starlet"。
通常,如果 sb 引用 StringBuilder 的实例,则 sb.append(x) 和 sb.insert(sb.length(), x) 具有相同的效果。 每个字符串生成器都有一定的容量。只要字符串生成器所包含的字符序列的长度没有超出此容量,就无需分配新的内部缓冲区。如果内部缓冲区溢出,则此容量自动增大。
将 StringBuilder 的实例用于多个线程是不安全的。如果需要这样的同步,则建议使用 StringBuffer。
[3] wave混音的兑现(2)
来源: 互联网 发布时间: 2014-02-18
wave混音的实现(2)
关于混音算法,参考的是http://jacky-zhang.iteye.com/blog/766053,下面是具体的实现逻辑
关于混音算法,参考的是http://jacky-zhang.iteye.com/blog/766053,下面是具体的实现逻辑
package example.audio; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import javax.microedition.io.Connector; import javax.microedition.io.HttpConnection; import javax.microedition.io.file.FileConnection; import javax.microedition.lcdui.Command; import javax.microedition.lcdui.CommandListener; import javax.microedition.lcdui.Display; import javax.microedition.lcdui.Displayable; import javax.microedition.lcdui.Form; import javax.microedition.media.Manager; import javax.microedition.media.MediaException; import javax.microedition.media.Player; import javax.microedition.media.PlayerListener; import javax.microedition.midlet.MIDlet; import javax.microedition.midlet.MIDletStateChangeException; public class Mixing2 extends MIDlet implements CommandListener{ private Command play1 = new Command("Play one", Command.OK, 0); private Command play2 = new Command("Play two", Command.OK, 1); private Command play3 = new Command("Play three", Command.OK, 6); private Command stop1 = new Command("Stop one", Command.CANCEL, 2); private Command stop2 = new Command("stop two", Command.CANCEL, 3); private Command stop3 = new Command("stop three", Command.CANCEL, 7); private Command playMix = new Command("play mix", Command.OK, 4); private Command stopRecord = new Command("stop record", Command.OK, 5); private Player player1; private Player player2; private Player player3; private Player player4; private String[] urls = {"/128kbps/intwap-5.wav","/128kbps/intwap-6.wav","/128kbps/intwap-7.wav"}; private Form form = new Form("Test mixing"); private byte[][] data = new byte[3][]; private int[][] times = new int[3][]; private long startTime = 0; private long size; private int idx1 = 0; private int idx2 = 0; private int idx3 = 0; private static final int FIRST = 1; private static final int SECOND = 2; private static final int THIRD = 3; private boolean start = false; public Mixing2() {} protected void destroyApp(boolean arg0) throws MIDletStateChangeException { } protected void pauseApp() { } protected void startApp() throws MIDletStateChangeException { form.addCommand(play1); form.addCommand(stop1); form.addCommand(play2); form.addCommand(stop2); form.addCommand(play3); form.addCommand(stop3); form.addCommand(playMix); form.addCommand(stopRecord); form.setCommandListener(this); Display.getDisplay(this).setCurrent(form); } public void commandAction(Command arg0, Displayable arg1) { if (arg0 == play1) { form.append("play one"); if(startTime == 0) startTime = System.currentTimeMillis(); new Thread(){ public void run() { try { stopPlayer1(); (player1 = initPlayer(FIRST)).start(); } catch (MediaException e) { e.printStackTrace(); } } }.start(); System.out.println("player1.start.time: "+System.currentTimeMillis()); } else if (arg0 == stop1) { stopPlayer1(); } else if (arg0 == play2) { form.append("play two"); if(startTime == 0) startTime = System.currentTimeMillis(); new Thread(){ public void run() { try { stopPlayer2(); (player2 = initPlayer(SECOND)).start(); } catch (MediaException e) { e.printStackTrace(); } } }.start(); } else if (arg0 == stop2) { stopPlayer2(); } else if (arg0 == play3) { form.append("play three"); if(startTime == 0) startTime = System.currentTimeMillis(); new Thread(){ public void run() { try { stopPlayer3(); (player3 = initPlayer(THIRD)).start(); } catch (MediaException e) { e.printStackTrace(); } } }.start(); } else if (arg0 == stop3) { stopPlayer3(); } else if (arg0 == playMix) { new Thread(){ public void run() { try { ByteArrayOutputStream bos = new ByteArrayOutputStream(); byte[] data = mixing(); System.out.println("combine.................data "+data.length); try { bos.write(new WaveHeader(data.length, (short)16, 8000).getHeader()); bos.write(data); } catch (IOException e) { e.printStackTrace(); } System.out.println("ready....stop....player........ "); stopPlayer4(); System.out.println("ready....mix....player........ "); player4 = Manager.createPlayer(new ByteArrayInputStream(bos.toByteArray()), "audio/x-wav"); player4.prefetch(); player4.realize(); player4.start(); } catch (IOException e) { e.printStackTrace(); } catch (MediaException e) { e.printStackTrace(); } System.out.println("playing.........mix.......data "); for(int i=0;i<times.length;i++){ times[i] = null; } startTime = 0; idx1 = idx2 = idx3 = 0; }; }.start(); } else if (arg0 == stopRecord) { stopPlayer1(); stopPlayer2(); stopPlayer3(); System.gc(); } } private void saveToDisk(){ // FileConnection file = (FileConnection)Connector.open("file://localhost/" + ); } private byte[] mixing(){ size = (System.currentTimeMillis() - startTime) * 16; long start = System.currentTimeMillis(); byte[] mixData = new byte[(int) size]; byte[][] mixPices = new byte[times.length][]; System.out.println("111111111111: "+size); for(int i=0; i< times.length;i++){ if(times[i]==null) continue; mixPices[i] = new byte[(int) size]; int length = data[i].length-44; for(int j =0; j<times[i].length;j++){ if(times[i][j]==0)break; System.out.println("player"+i+".time: "+times[i][j]); if((j+1)%2==0)System.out.println((times[i][j]-times[i][j-1])); if((j+1)%2==0) { int max = times[i][j]-times[i][j-1]; for (int k = 44; k < max; k++){ if(k >= length) break; mixPices[i][(int) times[i][j-1]+k-44] = data[i][k]; } } } } System.out.println("999999999999: "+(System.currentTimeMillis() - start)); double f = 1.0f; int MAX = 127, MIN = -127; double STEPSIZE; for(int m=0;m<mixData.length;m++){ mixData[m] = 0; double temp = 0; for(int n =0;n<mixPices.length;n++){ if(mixPices[n]==null) continue; temp += mixPices[n][m]; } if(temp==0) continue; temp = temp * f; if(temp>MAX){ double f0 = 127.0f/temp; f = f0; temp = MAX; } else if(temp < MIN){ double f0 = -127.0f/temp; f = f0; temp = (byte) MIN; } if(f<1) { STEPSIZE = ((1.0f-f)/16); f += STEPSIZE; } mixData[m] = (byte) temp; } for(int n =0;n<mixPices.length;n++){ mixPices[n] = null; } mixPices = null; System.out.println("mix cost time: "+(System.currentTimeMillis()-start)); return mixData; } private Player initPlayer(int p){ byte[] temp = null; PlayerListener plistener = null; if( p == FIRST) { if (data[0]==null) { data[0] = getWaveData(urls[0]); } temp = data[0]; plistener = p1; } else if(p==SECOND) { if(data[1]==null){ data[1] = getWaveData(urls[1]); } temp = data[1]; plistener = p2; } else if(p==THIRD) { if(data[2]==null){ data[2] = getWaveData(urls[2]); } temp = data[2]; plistener = p3; } Player player = null; try { InputStream is = new ByteArrayInputStream(temp); player = Manager.createPlayer(is, "audio/x-wav"); player.prefetch(); player.realize(); player.addPlayerListener(plistener); // player.setLoopCount(-1); } catch (MediaException e) { e.printStackTrace(); }catch (IOException e) { e.printStackTrace(); } return player; } private void stopPlayer1(){ if(player1!=null && player1.getState() != Player.CLOSED){ form.append("stop one"); try { player1.stop(); player1.close(); player1 = null; // System.gc(); } catch (MediaException e) { e.printStackTrace(); } } } private void stopPlayer2(){ if(player2!=null && player2.getState() != Player.CLOSED){ form.append("stop two"); try { player2.stop(); player2.close(); player2 = null; // System.gc(); } catch (MediaException e) { e.printStackTrace(); } } } private void stopPlayer3(){ if(player3!=null && player3.getState() != Player.CLOSED){ form.append("stop three"); try { player3.stop(); player3.close(); player3 = null; // System.gc(); } catch (MediaException e) { e.printStackTrace(); } } } private void stopPlayer4(){ if(player4!=null && player4.getState() != Player.CLOSED){ form.append("stop mix"); try { player4.stop(); player4.close(); player4 = null; // System.gc(); } catch (MediaException e) { e.printStackTrace(); } } } PlayerListener p1 = new PlayerListener(){ public void playerUpdate(Player arg0, String arg1, Object arg2) { if(arg1.equals(PlayerListener.END_OF_MEDIA)){ System.out.println("end of media"); // System.out.println(System.currentTimeMillis()); times[0][idx1] = (int) ((System.currentTimeMillis() - startTime) * 16); idx1++; System.out.println(" player1.cost.time: "+arg0.getMediaTime()); } else if(arg1.equals(PlayerListener.STOPPED)){ System.out.println("stopped"); times[0][idx1] = (int) ((System.currentTimeMillis() - startTime) * 16); idx1++; // System.out.println(System.currentTimeMillis()); } else if(arg1.equals(PlayerListener.STARTED)){ System.out.println("started"); if(times[0] == null) times[0] = new int[100]; times[0][idx1] = (int) ((System.currentTimeMillis() - startTime) * 16); idx1++; System.out.println(System.currentTimeMillis()); } } }; PlayerListener p2 = new PlayerListener(){ public void playerUpdate(Player arg0, String arg1, Object arg2) { if(arg1.equals(PlayerListener.STARTED)){ System.out.println("started"); if(times[1] == null) times[1] = new int[100]; times[1][idx2] = (int) ((System.currentTimeMillis() - startTime) * 16); idx2++; // System.out.println(System.currentTimeMillis()); } else if(arg1.equals(PlayerListener.STOPPED)){ System.out.println("stopped"); times[1][idx2] = (int) ((System.currentTimeMillis() - startTime) * 16); idx2++; // System.out.println(System.currentTimeMillis()); } else if(arg1.equals(PlayerListener.END_OF_MEDIA)){ System.out.println(player2.getState()); times[1][idx2] = (int) ((System.currentTimeMillis() - startTime) * 16); idx2++; } } }; PlayerListener p3 = new PlayerListener(){ public void playerUpdate(Player arg0, String arg1, Object arg2) { if(arg1.equals(PlayerListener.STARTED)){ System.out.println("started"); if(times[2] == null) times[2] = new int[100]; times[2][idx3] = (int) ((System.currentTimeMillis() - startTime) * 16); idx3++; // System.out.println(System.currentTimeMillis()); } else if(arg1.equals(PlayerListener.STOPPED)){ System.out.println("stopped"); times[2][idx3] = (int) ((System.currentTimeMillis() - startTime) * 16); idx3++; // System.out.println(System.currentTimeMillis()); } else if(arg1.equals(PlayerListener.END_OF_MEDIA)){ System.out.println(player3.getState()); times[2][idx3] = (int) ((System.currentTimeMillis() - startTime) * 16); idx3++; } } }; private byte[] getWaveData(String url){ ByteArrayOutputStream bos = new ByteArrayOutputStream(); InputStream is = getClass().getResourceAsStream(url); // int m = 0; byte[] d = new byte[2048]; while(true){ try { int t = is.read(d); // m = is.read(); if(t==-1) break; bos.write(d); } catch (IOException e) { e.printStackTrace(); } } byte[] data = bos.toByteArray(); System.out.println(data.length); try { is.close(); bos.close(); } catch (IOException e) { e.printStackTrace(); } return data; } }
最新技术文章: