java - AudioTrack 只播放噪音而不是录制的语音
问题描述
我想使用音轨播放录制的语音,但它会发出噪音我尝试了不同的技术但无法解决这个问题。我改变了:频率速率,音频格式通道音频格式编码
public class PlayAudio extends AsyncTask<Void, Integer, Void> {
PlayAudio playTask;
String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/MyFolder/";
String myfile = path + "filename" + ".wav";
File recordingFile = new File(myfile);
boolean isRecording = false,isPlaying = false;
int frequency = 44100 ,channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
@Override
protected Void doInBackground(Void... params) {
isPlaying = true;
int bufferSize = AudioTrack.getMinBufferSize(frequency,channelConfiguration,audioEncoding);
short[] audiodata = new short[bufferSize / 4];
try {
DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream(recordingFile)));
AudioTrack audioTrack = new AudioTrack(
AudioManager.STREAM_MUSIC, frequency,
channelConfiguration, audioEncoding, bufferSize,
AudioTrack.MODE_STREAM);
audioTrack.play();
while (isPlaying && dis.available() > 0) {
int i = 0;
while (dis.available() > 0 && i < audiodata.length) {
audiodata[i] = dis.readShort();
i++;
}
audioTrack.write(audiodata, 0, audiodata.length);
}
dis.close();
// startPlaybackButton.setEnabled(false);
// stopPlaybackButton.setEnabled(true);
} catch (Throwable t) {
Log.e("AudioTrack", "Playback Failed");
}
return null;
}
}
解决方案
我不知道这是否是全部问题,但您的部分问题是您将 wav 文件视为所有音频数据。事实上,那里有相当数量的元数据。有关详细信息,请参阅http://soundfile.sapp.org/doc/WaveFormat/。
最安全的做法是解析文件直到找到数据块,然后读取数据块,然后停止(因为通常在数据块之后也有元数据。
这里有一些粗略的代码可以给你这个想法。
try {
byte[] buffer = new byte[1024];
// First find the data chunk
byte[] bytes = new byte[4];
// Read first 4 bytes.
// (Should be RIFF descriptor.)
// Assume it's ok
is.read(bytes);
// First subchunk will always be at byte 12.
// (There is no other dependable constant.)
is.skip(8);
for (;;) {
// Read each chunk descriptor.
if (is.read(bytes) < 0) {
break;
}
String desc = new String(bytes, "US-ASCII");
// Read chunk length.
if (is.read(bytes) < 0) {
break;
}
int dataLength = (
(bytes[0] & 0xFF) |
((bytes[1] & 0xFF) << 8) |
((bytes[2] & 0xFF) << 16) |
((bytes[3] & 0xFF) << 24));
long length = getUnsignedInt(dataLength);
if (desc.equals("data")){
// Read 'length' bytes
...
public static long getUnsignedInt(int x) {
return x & 0x00000000ffffffffL;
}
推荐阅读
- html - 如何重新关注第一个弹出窗口?
- javascript - 如何在反应中缓存/保存图像并显示它们?
- ruby-on-rails - 获救时的自定义异常会给出名称错误?
- postgresql - 错误:行太大:大小 8168,最大大小 8164
- twitter-bootstrap - Bootstrap 3 到 Bootstrap 4 隐藏元素
- android - android - 如何在点击小部件时调用正在运行的服务类的方法?
- asp.net - 单选按钮导致奇怪的行为
- php - 获取类别的id
- oauth - Gmail 登录的工作原理
- javascript - 如何在本例中使用 org.singlespaced.d3js 的数据函数实例化 scala.scalajs.js.ThisFunction3