[英]Can't play a reversed .wav file with MediaPlayer
我创建了一个录制音频的应用程序,将样本保存到sd卡中,然后使用“记录”和“播放”按钮进行播放。 我需要扭转这个例子。 我可以做所有的事情,反向采样以不同的名称保存在SD卡上。 原始样本为test.wav
,而反向的相同样本另存为revFile.wav
。 当我尝试播放revFile.wav
Android表示无法播放此格式。
我已经将样本放在一个数组中,然后颠倒了内容,这告诉我样本的开头可能有标题信息,需要首先剥离任何想法。 谢谢。
这是我到目前为止所拥有的。
public class recorder extends Activity {
MediaRecorder myRecorder = null;
DataInputStream dis = null;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
public void onClickPlay(View v){
Log.v("onClickplay", "play clicked");
try{
MediaPlayer mp = new MediaPlayer();
mp.setDataSource(Environment.getExternalStorageDirectory().getPath() + "/test.wav");
mp.prepare();
mp.start();
} catch(Exception e3) {
e3.printStackTrace();
}
TextView text = (TextView)findViewById(R.id.TextView01);
text.setText("playing");
}
public void onClickRecord(View v){
Log.v("onClickRecord", "record clicked");
File path = Environment.getExternalStorageDirectory();
Log.v("file path", ""+path.getAbsolutePath());
File file = new File(path, "test.wav");
if(file.exists()){
file.delete();
}
path.mkdirs();
Log.v("file path", ""+file.getAbsolutePath());
myRecorder = new MediaRecorder();
myRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
myRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
myRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
myRecorder.setOutputFile(file.getAbsolutePath());
Log.i("myrecorder", "about to prepare recording");
try{
myRecorder.prepare();
} catch(Exception e) {
e.printStackTrace();
}
Log.i("myrecorder", "prepared");
myRecorder.start(); // Recording is now started
Log.i("myrecorder", "recording");
TextView text = (TextView)findViewById(R.id.TextView01);
text.setText("recording");
}
public void onClickStop(View v){
Log.v("onClickStop", "stop clicked");
try{
myRecorder.stop();
myRecorder.reset(); // You can reuse the object by going back to setAudioSource() step
myRecorder.release(); // Now the object cannot be reused
}catch(Exception e){}
TextView text = (TextView)findViewById(R.id.TextView01);
text.setText("recording stopped");
}
public void onClickReverse(View v){
Log.v("onClickReverse", "reverse clicked");
File f = Environment.getExternalStorageDirectory();
String path = f.getAbsolutePath();
path = path + "/test.wav";
Log.v("path = ", ""+path);
Log.v("dir = ", ""+f.getAbsolutePath());
Log.v("test file exists? = ", ""+f.getAbsolutePath()+"/test.wav");
File f2 = new File(path);
Log.v("f2 = ", ""+f2.getAbsolutePath());
try {
InputStream is = new FileInputStream(f2);
BufferedInputStream bis = new BufferedInputStream(is);
dis = new DataInputStream(bis);
} catch (Exception e) {
e.printStackTrace();
}
int fileLength = (int)f2.length();
byte[] buffer = new byte[fileLength];
/*File reversedFile = Environment.getExternalStorageDirectory();
File revFile = new File(reversedFile, "reversedFile.wav");
Log.v("reversedfile path", ""+ revFile.getAbsolutePath());
if(revFile.exists()){
revFile.delete();
}
reversedFile.mkdirs();
*/
byte[] byteArray = new byte[fileLength +1];
Log.v("bytearray size = ", ""+byteArray.length);
try {
while(dis.read(buffer) != -1 ) {
dis.read(buffer);
Log.v("about to read buffer", "buffer");
byteArray = buffer;
}
Log.v(" buffer size = ", ""+ buffer.length);
} catch (IOException e) {
e.printStackTrace();
}
byte[] tempArray = new byte[fileLength];
int j=0;
for (int i=byteArray.length-1; i >=0; i--) {
tempArray[ j++ ] = byteArray[i];
}
File revPath = Environment.getExternalStorageDirectory();
Log.v("revpath path", ""+revPath.getAbsolutePath());
File revFile = new File(revPath, "revFile.wav");
Log.v("revfile path ", ""+revFile.getAbsolutePath());
if(revFile.exists()){
revFile.delete();
}
revPath.mkdirs();
try {
OutputStream os = new FileOutputStream(revFile);
BufferedOutputStream bos = new BufferedOutputStream(os);
DataOutputStream dos = new DataOutputStream(bos);
Log.v("temparray size = ", ""+ tempArray.length);
dos.write(tempArray);
dos.flush();
dos.close();
} catch (Exception e) {
e.printStackTrace();
}
try{
MediaPlayer mp = new MediaPlayer();
mp.setDataSource(Environment.getExternalStorageDirectory().getPath()
+"/revFile.wav");
mp.prepare();
mp.start();
} catch(Exception e3) {
e3.printStackTrace();
}
TextView text = (TextView)findViewById(R.id.TextView01);
text.setText("playing reversed file");
}
}// end of onclickrev
链接文本中对.WAV标头有很好的描述
还要注意,文件中的所有数据都按Little Endian顺序存储(1个多字节数字的低位字节存储在最低地址中……),因此您不能只反转字节。 您需要查看每个样本有多少个字节宽(通常为16个字节,但请检查标头),然后以该大小的块将它们反转
WAV文件格式包括一个44字节的标题块。 大多数WAV文件都包含此44字节的标题,后跟实际的样本数据。 因此,扭转WAV文件,你应该先复制原始文件的字节44头, 然后头后倒样本数据从原来的复制。 如果您只是反转原始整个文件的字节顺序,则绝对无法使用。 它也不会工作,如果你复制标题,然后反转文件的剩余部分的字节顺序(实际上是将整理的工作,但你得到的将只是噪声)。 您实际上需要反转帧 ,其中帧大小取决于每个样本的字节数以及文件是立体声还是单声道(例如,如果文件是立体声且每个样本2字节,则每个帧为4字节) )。
请注意,并非所有的WAV文件都是这样的“规范”文件。 WAV文件实际上是RIFF文件的变体,因此从技术上讲,您需要复杂得多的代码才能在原始文件中查找标头和样本数据的各个部分。 但是,大多数WAV文件只是样本后面的标头(如果您自己录制音频,这肯定是正确的),在这种情况下,您可以节省很多工作。
Joe Cullity
的链接很好地描述了WAV文件格式。
我很确定您是对的,问题是您不能仅仅破坏文件中的字节来反转波形,因为这破坏了标头信息。 您应该尝试看看是否有一个好的库可以执行此操作,因为我对.wav文件的使用经验很少。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.