Android : 播放 PCM 文件时出错
Android : Error While Playing a PCM File
我正在尝试播放从麦克风录制音频时创建的 PCM 文件。
我正在使用 AudioRecord,因为我想分析麦克风录制的声音的频率。
播放PCM文件的代码片段如下。但是当我尝试播放文件时,播放时有很大的噪音。
FileInputStream fis=null;
File l=null;
l=new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/Notate/f1.pcm");
byte[] buffer=new byte[(int)l.length()];
try {
fis = new FileInputStream(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Notate/f1.pcm");
fis.read(buffer);
}
catch(Exception e)
{
}
int intSize = android.media.AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT);
AudioTrack at = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT, intSize, AudioTrack.MODE_STREAM);
if (at!=null) {
at.play();
at.write(buffer, 0, buffer.length);
at.stop();
at.release();
}
用于存储PCM文件的代码如下。
private class RecordAudio extends AsyncTask<Void, Double, Void> {
FileOutputStream os = null;
BufferedOutputStream bos =null;
DataOutputStream dos = null;
@Override
protected Void doInBackground(Void... params) {
int bufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioEncoding); // Gets the minimum buffer needed
AudioRecord audioRecord = new AudioRecord(audioSource, sampleRate, channelConfig, audioEncoding, bufferSize); // The RAW PCM sample recording
File f=new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/Notate/");
if(!f.isDirectory()) {
File newDirectory = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Notate/");
newDirectory.mkdirs();
}
String filepath=Environment.getExternalStorageDirectory().getAbsolutePath()+"/Notate/f1.pcm";
short[] buffer = new short[blockSize]; // Save the raw PCM samples as short bytes
try{
os=new FileOutputStream(filepath);
}
catch(FileNotFoundException e)
{
}
bos = new BufferedOutputStream(os);
dos = new DataOutputStream(bos);
try {
audioRecord.startRecording(); //Start
} catch (Throwable t) {
}
while (started) {
int length=audioRecord.read(buffer, 0, blockSize);
Yin alpha = new Yin(44100, 1024, 0.2);
float[] floaters = new float[buffer.length];
for (int i = 0; i < buffer.length; i++) {
floaters[i] = buffer[i];
}
for(int k=0;k<length;k++) {
try {
dos.writeShort(buffer[k]);
} catch (IOException e) {
}
}
float result = alpha.getPitch(floaters);
publishProgress((double) result);
}
try{
dos.close();
}
catch(IOException e){
e.printStackTrace();
}
return null;
}
writeShort
以大端布局写入值,即最高有效字节在前,而 AudioTrack
可能期望样本是小端(最低有效字节在前)。
如果您在录制时使用 byte[]
而不是 short[]
,您的事情会变得更简单。然后你可以简单地用 dos.write(buffer, 0, length);
写信给你的 DataOutputStream
。在这种情况下,您必须对浮点值的转换进行一些修改:
for (int i = 0; i < length; i += 2) {
floaters[i] = (short)(buffer[i] | (buffer[i+1] << 8));
}
我正在尝试播放从麦克风录制音频时创建的 PCM 文件。
我正在使用 AudioRecord,因为我想分析麦克风录制的声音的频率。
播放PCM文件的代码片段如下。但是当我尝试播放文件时,播放时有很大的噪音。
FileInputStream fis=null;
File l=null;
l=new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/Notate/f1.pcm");
byte[] buffer=new byte[(int)l.length()];
try {
fis = new FileInputStream(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Notate/f1.pcm");
fis.read(buffer);
}
catch(Exception e)
{
}
int intSize = android.media.AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT);
AudioTrack at = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT, intSize, AudioTrack.MODE_STREAM);
if (at!=null) {
at.play();
at.write(buffer, 0, buffer.length);
at.stop();
at.release();
}
用于存储PCM文件的代码如下。
private class RecordAudio extends AsyncTask<Void, Double, Void> {
FileOutputStream os = null;
BufferedOutputStream bos =null;
DataOutputStream dos = null;
@Override
protected Void doInBackground(Void... params) {
int bufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioEncoding); // Gets the minimum buffer needed
AudioRecord audioRecord = new AudioRecord(audioSource, sampleRate, channelConfig, audioEncoding, bufferSize); // The RAW PCM sample recording
File f=new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/Notate/");
if(!f.isDirectory()) {
File newDirectory = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Notate/");
newDirectory.mkdirs();
}
String filepath=Environment.getExternalStorageDirectory().getAbsolutePath()+"/Notate/f1.pcm";
short[] buffer = new short[blockSize]; // Save the raw PCM samples as short bytes
try{
os=new FileOutputStream(filepath);
}
catch(FileNotFoundException e)
{
}
bos = new BufferedOutputStream(os);
dos = new DataOutputStream(bos);
try {
audioRecord.startRecording(); //Start
} catch (Throwable t) {
}
while (started) {
int length=audioRecord.read(buffer, 0, blockSize);
Yin alpha = new Yin(44100, 1024, 0.2);
float[] floaters = new float[buffer.length];
for (int i = 0; i < buffer.length; i++) {
floaters[i] = buffer[i];
}
for(int k=0;k<length;k++) {
try {
dos.writeShort(buffer[k]);
} catch (IOException e) {
}
}
float result = alpha.getPitch(floaters);
publishProgress((double) result);
}
try{
dos.close();
}
catch(IOException e){
e.printStackTrace();
}
return null;
}
writeShort
以大端布局写入值,即最高有效字节在前,而 AudioTrack
可能期望样本是小端(最低有效字节在前)。
如果您在录制时使用 byte[]
而不是 short[]
,您的事情会变得更简单。然后你可以简单地用 dos.write(buffer, 0, length);
写信给你的 DataOutputStream
。在这种情况下,您必须对浮点值的转换进行一些修改:
for (int i = 0; i < length; i += 2) {
floaters[i] = (short)(buffer[i] | (buffer[i+1] << 8));
}