Java實(shí)現(xiàn)多個(gè)wav文件合成一個(gè)的方法示例
本文實(shí)例講述了Java實(shí)現(xiàn)多個(gè)wav文件合成一個(gè)的方法。分享給大家供大家參考,具體如下:
前面一篇介紹了java切割wav音頻文件的方法,這里再給出合并多個(gè)wav音頻文件的方法。
package com.cmos.nomsapp.utils.wavmeger; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.ArrayList; import java.util.List; /** * 獲取wav頭文件然后合并成單個(gè)wav * @author zcf * @date 2017-10-17 */ public class WavMergeUtil { /** * meger多個(gè)wav * @param inputs 多個(gè)wav * @param output 要生成的wav * @throws IOException */ public static void mergeWav(File[] inputs, String output) throws IOException { if (inputs.length < 1) { return; } try(FileInputStream fis = new FileInputStream(inputs[0]); FileOutputStream fos = new FileOutputStream(new File(output))){ byte[] buffer = new byte[1024 * 4]; int total = 0; int count; while ((count = fis.read(buffer)) > -1) { fos.write(buffer, 0, count); total += count; } fis.close(); for (int i = 1; i < inputs.length; i++) { File file = inputs[i]; try(FileInputStream fisH = new FileInputStream(file)){ Header header = resolveHeader(fisH); FileInputStream dataInputStream = header.dataInputStream; while ((count = dataInputStream.read(buffer)) > -1) { fos.write(buffer, 0, count); total += count; } } } fos.flush(); fos.close(); FileInputStream fisHo = new FileInputStream(new File(output)); Header outputHeader = resolveHeader(fisHo); outputHeader.dataInputStream.close(); try(RandomAccessFile res = new RandomAccessFile(output, "rw")){ res.seek(4); byte[] fileLen = intToByteArray(total + outputHeader.dataOffset - 8); res.write(fileLen, 0, 4); res.seek(outputHeader.dataSizeOffset); byte[] dataLen = intToByteArray(total); res.write(dataLen, 0, 4); } } } /** * 解析頭部,并獲得文件指針指向數(shù)據(jù)開(kāi)始位置的InputStreram,記得使用后需要關(guān)閉 */ private static Header resolveHeader(FileInputStream fis) throws IOException { byte[] byte4 = new byte[4]; byte[] buffer = new byte[2048]; int readCount = 0; Header header = new Header(); fis.read(byte4);// RIFF fis.read(byte4); readCount += 8; header.fileSizeOffset = 4; header.fileSize = byteArrayToInt(byte4); fis.read(byte4);// WAVE fis.read(byte4);// fmt fis.read(byte4); readCount += 12; int fmtLen = byteArrayToInt(byte4); fis.read(buffer, 0, fmtLen); readCount += fmtLen; fis.read(byte4);// data or fact readCount += 4; if (isFmt(byte4, 0)) {// 包含fmt段 fis.read(byte4); int factLen = byteArrayToInt(byte4); fis.read(buffer, 0, factLen); fis.read(byte4);// data readCount += 8 + factLen; } fis.read(byte4);// data size int dataLen = byteArrayToInt(byte4); header.dataSize = dataLen; header.dataSizeOffset = readCount; readCount += 4; header.dataOffset = readCount; header.dataInputStream = fis; return header; } private static boolean isRiff(byte[] bytes, int start) { if (bytes[start + 0] == 'R' && bytes[start + 1] == 'I' && bytes[start + 2] == 'F' && bytes[start + 3] == 'F') { return true; } else { return false; } } private static boolean isFmt(byte[] bytes, int start) { if (bytes[start + 0] == 'f' && bytes[start + 1] == 'm' && bytes[start + 2] == 't' && bytes[start + 3] == ' ') { return true; } else { return false; } } private static boolean isData(byte[] bytes, int start) { if (bytes[start + 0] == 'd' && bytes[start + 1] == 'a' && bytes[start + 2] == 't' && bytes[start + 3] == 'a') { return true; } else { return false; } } /** * 將int轉(zhuǎn)化為byte[] */ private static byte[] intToByteArray(int data) { return ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(data).array(); } /** * 將short轉(zhuǎn)化為byte[] */ private static byte[] shortToByteArray(short data) { return ByteBuffer.allocate(2).order(ByteOrder.LITTLE_ENDIAN).putShort(data).array(); } /** * 將byte[]轉(zhuǎn)化為short */ private static short byteArrayToShort(byte[] b) { return ByteBuffer.wrap(b).order(ByteOrder.LITTLE_ENDIAN).getShort(); } /** * 將byte[]轉(zhuǎn)化為int */ private static int byteArrayToInt(byte[] b) { return ByteBuffer.wrap(b).order(ByteOrder.LITTLE_ENDIAN).getInt(); } /** * 頭部部分信息 */ static class Header { public int fileSize; public int fileSizeOffset; public int dataSize; public int dataSizeOffset; public int dataOffset; public FileInputStream dataInputStream; } }
更多關(guān)于java算法相關(guān)內(nèi)容感興趣的讀者可查看本站專(zhuān)題:《Java文件與目錄操作技巧匯總》、《Java數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Java操作DOM節(jié)點(diǎn)技巧總結(jié)》和《Java緩存操作技巧匯總》
希望本文所述對(duì)大家java程序設(shè)計(jì)有所幫助。
- java實(shí)現(xiàn)切割wav音頻文件的方法詳解【附外部jar包下載】
- java讀取wav文件(波形文件)并繪制波形圖的方法
- java音頻播放示例分享(java如何播放音頻)
- Java使用IO流實(shí)現(xiàn)音頻的剪切和拼接
- 實(shí)例解析使用Java實(shí)現(xiàn)基本的音頻播放器的編寫(xiě)要點(diǎn)
- 代碼分析JAVA中PCM人聲音頻變聲處理
- 使用javax.sound實(shí)現(xiàn)簡(jiǎn)單音頻播放
- java實(shí)現(xiàn)音頻文件播放功能
- java實(shí)現(xiàn)大文件分割與合并的實(shí)例代碼
- java 實(shí)現(xiàn)切割文件和合并文件的功能
- Java實(shí)現(xiàn)大文件的切割與合并操作示例
相關(guān)文章
SpringSecurity+Mysql數(shù)據(jù)庫(kù)實(shí)現(xiàn)用戶安全登錄認(rèn)證的實(shí)踐
Spring Security 是一個(gè)提供身份認(rèn)證、授權(quán)和防范常見(jiàn)攻擊的安全權(quán)限框架,本文主要介紹了SpringSecurity+Mysql數(shù)據(jù)庫(kù)實(shí)現(xiàn)用戶安全登錄認(rèn)證的實(shí)踐,具有一定的參考價(jià)值,感興趣的可以了解一下2024-08-08mybatis中一對(duì)一關(guān)系association標(biāo)簽的使用
這篇文章主要介紹了mybatis中一對(duì)一關(guān)系association標(biāo)簽的使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03淺談Java實(shí)現(xiàn)面向?qū)ο缶幊蘪ava oop
這篇文章主要介紹了淺談Java實(shí)現(xiàn)面向?qū)ο缶幊蘪ava oop,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07SpringBoot重啟后,第一次請(qǐng)求接口請(qǐng)求慢的問(wèn)題及解決
這篇文章主要介紹了SpringBoot重啟后,第一次請(qǐng)求接口請(qǐng)求慢的問(wèn)題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-05-05Spring Boot Mysql 數(shù)據(jù)庫(kù)操作示例
本篇文章主要介紹了Spring Boot Mysql 數(shù)據(jù)庫(kù)操作示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-02-02springboot應(yīng)用中靜態(tài)資源訪問(wèn)與接口請(qǐng)求沖突問(wèn)題解決
這篇文章主要介紹了springboot應(yīng)用中靜態(tài)資源訪問(wèn)與接口請(qǐng)求沖突,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-06-06JDBC如何訪問(wèn)MySQL數(shù)據(jù)庫(kù),并增刪查改
這篇文章主要介紹了JDBC如何訪問(wèn)MySQL數(shù)據(jù)庫(kù),幫助大家更好的理解和學(xué)習(xí)java與MySQL,感興趣的朋友可以了解下2020-08-08Java數(shù)據(jù)結(jié)構(gòu)之二叉排序樹(shù)的實(shí)現(xiàn)
二叉排序樹(shù)(Binary Sort Tree),又稱(chēng)二叉查找樹(shù)(Binary Search Tree),亦稱(chēng)二叉搜索樹(shù)。本文詳細(xì)介紹了二叉排序樹(shù)的原理,并且提供了Java代碼的完全實(shí)現(xiàn)。需要的可以參考一下2022-01-01