[英]Convert .pcm file to .wav file
我需要在我的 Android 應用程序中將.pcm 文件轉換為.wav 文件。 PCM 錄音是原始數字音頻樣本。 以前,一個 PCM 音頻文件是以 16000 的采樣頻率錄制的,在單聲道模式下(channelConfigurationRecord = AudioFormat.CHANNEL_IN_MONO),一個樣本中的 16 位(audioEncoding = AudioFormat.ENCODING_PCM_16BIT)。 要將 PCM 轉換為 WAV,我需要先編寫一個 header,然后添加我所有的 PCM 數據。 我花了很多時間在這上面,我嘗試了很多變種,但沒有任何效果。 我不知道我做錯了什么......幫幫我!
public class Convert {
File filePcm;
File fileWav;
char chunkId[]={'R','I','F','F'};
byte chunkSize[];
char format[]={'W','A','V','E'};
char subchunk1Id[]={'f','m','t',' '};
byte subchunk1Size[]={0b0,0b0,0b0,16};
byte audioFormat[]={0,1};
byte numChannels[]={0,1};
byte sampleRate[]={0b0,0b0,0b111110,(byte)0b10000000};
byte byteRate[]={0b0,0b0,0b1111101,0b0};
byte blockAlign[]={0,2};
byte bitsPerSample[]={0,16};
char subchunk2Id[]={'d','a','t','a'};
byte subchunk2Size[];
public Convert (File filePcm){
this.filePcm = filePcm;
}
public void convertWavFile(){
try {
fileWav = new File("");
fileWav.createNewFile();
writeHeader();
writePcmData();
} catch (IOException e) {
e.printStackTrace();
}
}
private void writeHeader() throws IOException {
long chunkSiz=36+filePcm.length();
chunkSize = new byte[]{ (byte) (chunkSiz & 0xff),
(byte) ((chunkSiz >> 8) & 0xff),
(byte) ((chunkSiz >> 16) & 0xff),
(byte) ((chunkSiz >> 24) & 0xff)};
long subchunk2Siz=filePcm.length();
subchunk2Size = new byte[]{ (byte) (subchunk2Siz & 0xff),
(byte) ((subchunk2Siz >> 8) & 0xff),
(byte) ((subchunk2Siz >> 16) & 0xff),
(byte) ((subchunk2Siz >> 24) & 0xff)};
FileOutputStream d = new FileOutputStream(fileWav);
for (char c:chunkId) d.write(c);
for (byte c:chunkSize) d.write(c);
for (char c:format) d.write(c);
for (char c:subchunk1Id) d.write(c);
for (byte c:subchunk1Size)d.write (c);
for (byte c:audioFormat)d.write (c);
for (byte c:numChannels)d.write (c);
for (byte c:sampleRate) d.write(c);
for (byte c:byteRate) d.write(c);
for (byte c:blockAlign)d.write (c);
for (byte c:bitsPerSample)d.write (c);
for (char c:subchunk2Id) d.write(c);
for (byte c:subchunk2Size) d.write(c);
}
private void writePcmData() throws IOException {
FileInputStream fileInputStream = new FileInputStream(filePcm);
FileOutputStream fileOutputStream = new FileOutputStream(fileWav);
int i;
while((i=fileInputStream.read())!=-1){
fileOutputStream.write(i);
}
}
}
輸入數據是未經處理的 pcm 樣本,在創建並寫入此 shell 后,該文件無法被任何播放器識別
首先添加 FFMPEG 庫,該庫可以輕松轉換、合並、混合視頻和音頻。
構建.gradle(應用程序)
implementation 'com.writingminds:FFmpegAndroid:0.3.2'
活動
File yourPcmFile = new File("YOUR_PCM_FILE_ABSOLUTE_PATH");
File yourWawOutput = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/output.wav");
String command = "-f s16le -ar 44.1k -ac 2 -i "+yourPcmFile.getAbsolutePath()+ yourWawOutput.getAbsolutePath();
FFmpeg ffmpeg = FFmpeg.getInstance(context);
try {
ffmpeg.loadBinary(new LoadBinaryResponseHandler() {
@Override
public void onStart() {
}
@Override
public void onFailure() {
}
@Override
public void onSuccess() {
}
@Override
public void onFinish() {
}
});
} catch (Exception e) {
Toast.makeText(context, e.getMessage(), Toast.LENGTH_SHORT).show();
}
try {
ffmpeg.execute(cmd, new ExecuteBinaryResponseHandler() {
@Override
public void onStart() {
dialog.show();
}
@Override
public void onProgress(String message) {
}
@Override
public void onFailure(String message) {
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
@Override
public void onSuccess(String message) {
Toast.makeText(context, "Build has been successful", Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
@Override
public void onFinish() {
}
});
} catch (Exception e) {
Toast.makeText(context, e.getMessage(), Toast.LENGTH_SHORT).show();
} finally {
if (ffmpeg.isFFmpegCommandRunning()) {
ffmpeg.killRunningProcesses();
顯現
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
更多信息
-f s16le -ar 44.1k -ac 2 -i "+yourPcmFile.getAbsolutePath()+ yourWawOutput.getAbsolutePath()
-f s16le >>> signed 16-bit little endian samples
-ar 44.1k >>> sample rate 44.1kHz
-ac 2 >>> 2 channels (stereo)
-i yourPcmFile.getAbsolutePath() >>> input file
yourWawOutput.getAbsolutePath() >>> output file
該文件是在 FileOutputStream object 實例化時創建的。 如果文件已存在,則將其覆蓋。
您正在創建文件兩次。
一次在 writeHeader() function 和一次 writePCM() function 中。
當您寫入 PCM 數據時,您正在覆蓋您寫入的 header 數據,並且您最終會得到另一個 PCM 文件。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.