欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java實(shí)現(xiàn)生成自定義時(shí)長(zhǎng)的靜音音頻

 更新時(shí)間:2022年01月27日 08:35:01   作者:劍客阿良_ALiang  
這篇文章主要介紹了如何通過(guò)Java實(shí)現(xiàn)一個(gè)音頻工具類,可以實(shí)現(xiàn)生成一段自定義時(shí)長(zhǎng)(精確到毫秒)的wav音頻。感興趣的小伙伴可以了解一下

Maven依賴

        <dependency>
            <groupId>org</groupId>
            <artifactId>jaudiotagger</artifactId>
            <version>2.0.1</version>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>30.1.1-jre</version>
        </dependency>

代碼

以16k采樣率,單聲道,16bits采樣分辨率為例,具體參數(shù)原理,下面有說(shuō)明。

import com.google.common.primitives.Bytes;

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;

/** @Author huyi @Date 2021/9/30 15:33 @Description: 靜音音頻工具類 */
public class SilenceAudioUtils {

? /**
? ?* 根據(jù)PCM文件構(gòu)建wav的header字段
? ?*
? ?* @param srate Sample rate - 8000, 16000, etc.
? ?* @param channel Number of channels - Mono = 1, Stereo = 2, etc..
? ?* @param format Number of bits per sample (16 here)
? ?* @throws IOException
? ?*/
? public static byte[] buildWavHeader(int dataLength, int srate, int channel, int format)
? ? ? throws IOException {
? ? byte[] header = new byte[44];

? ? long totalDataLen = dataLength + 36;
? ? long bitrate = srate * channel * format;

? ? header[0] = 'R';
? ? header[1] = 'I';
? ? header[2] = 'F';
? ? header[3] = 'F';
? ? header[4] = (byte) (totalDataLen & 0xff);
? ? header[5] = (byte) ((totalDataLen >> 8) & 0xff);
? ? header[6] = (byte) ((totalDataLen >> 16) & 0xff);
? ? header[7] = (byte) ((totalDataLen >> 24) & 0xff);
? ? header[8] = 'W';
? ? header[9] = 'A';
? ? header[10] = 'V';
? ? header[11] = 'E';
? ? header[12] = 'f';
? ? header[13] = 'm';
? ? header[14] = 't';
? ? header[15] = ' ';
? ? header[16] = (byte) format;
? ? header[17] = 0;
? ? header[18] = 0;
? ? header[19] = 0;
? ? header[20] = 1;
? ? header[21] = 0;
? ? header[22] = (byte) channel;
? ? header[23] = 0;
? ? header[24] = (byte) (srate & 0xff);
? ? header[25] = (byte) ((srate >> 8) & 0xff);
? ? header[26] = (byte) ((srate >> 16) & 0xff);
? ? header[27] = (byte) ((srate >> 24) & 0xff);
? ? header[28] = (byte) ((bitrate / 8) & 0xff);
? ? header[29] = (byte) (((bitrate / 8) >> 8) & 0xff);
? ? header[30] = (byte) (((bitrate / 8) >> 16) & 0xff);
? ? header[31] = (byte) (((bitrate / 8) >> 24) & 0xff);
? ? header[32] = (byte) ((channel * format) / 8);
? ? header[33] = 0;
? ? header[34] = 16;
? ? header[35] = 0;
? ? header[36] = 'd';
? ? header[37] = 'a';
? ? header[38] = 't';
? ? header[39] = 'a';
? ? header[40] = (byte) (dataLength & 0xff);
? ? header[41] = (byte) ((dataLength >> 8) & 0xff);
? ? header[42] = (byte) ((dataLength >> 16) & 0xff);
? ? header[43] = (byte) ((dataLength >> 24) & 0xff);

? ? return header;
? }

? /**
? ?* 默認(rèn)寫入的pcm數(shù)據(jù)是16000采樣率,16bit,可以按照需要修改
? ?*
? ?* @param filePath
? ?* @param pcmData
? ?*/
? public static boolean writeToFile(String filePath, byte[] pcmData) {
? ? BufferedOutputStream bos = null;
? ? try {
? ? ? bos = new BufferedOutputStream(new FileOutputStream(filePath));
? ? ? byte[] header = buildWavHeader(pcmData.length, 16000, 1, 16);
? ? ? bos.write(header, 0, 44);
? ? ? bos.write(pcmData);
? ? ? bos.close();
? ? ? return true;
? ? } catch (Exception e) {
? ? ? e.printStackTrace();
? ? } finally {
? ? ? if (bos != null) {
? ? ? ? try {
? ? ? ? ? bos.close();
? ? ? ? } catch (IOException e) {
? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? ? }
? ? }

? ? return false;
? }

? /**
? ?* 生成靜音音頻
? ?*
? ?* @param filePath 輸出文件地址
? ?* @param duration 音頻時(shí)長(zhǎng)
? ?*/
? public static void makeSilenceWav(String filePath, Long duration) {
? ? List<Byte> oldBytes = new ArrayList<>();
? ? IntStream.range(0, (int) (duration * 32)).forEach(x -> oldBytes.add((byte) 0));
? ? writeToFile(filePath, Bytes.toArray(oldBytes));
? }

? public static void main(String[] args) {
? ? makeSilenceWav("E:/csdn/1.wav", 5000L);
? }

運(yùn)行結(jié)果:

使用ffmpeg查看

參數(shù)說(shuō)明和使用方法

1、構(gòu)造原理

構(gòu)造一個(gè)wav主要分為兩個(gè)部分,頭文件和數(shù)據(jù)文件。那么只需要構(gòu)造一個(gè)全是靜音的音頻數(shù)據(jù)包,在加上頭就可以構(gòu)造出一個(gè)靜音文件。

所以代碼的主要邏輯就是構(gòu)造數(shù)據(jù)包->封裝文件頭。

2、怎么1毫秒的靜音包如何構(gòu)建呢?

這里首先要知道的是,音頻采樣率、采樣分辨率和聲道的概念。

這里分享一個(gè)簡(jiǎn)單的說(shuō)明鏈接: 詳解RIFF和WAVE音頻文件格式

而靜音就是每個(gè)采樣到的音頻包里面的內(nèi)容都是由(byte)0構(gòu)成的。

3、那么每毫秒的音頻包對(duì)應(yīng)多少個(gè)(byte)0呢?

這里有個(gè)公式:采樣率 x 聲道數(shù) x 采樣分辨率 / 8

參考鏈接: http://soundfile.sapp.org/doc/WaveFormat/

舉個(gè)例子:如果你要生成32k采樣率、雙聲道、16bits的靜音,每毫秒需要構(gòu)建幾個(gè)比特0呢?

按照公式: result = 32000 x 2 x 16 / 8000 = 128 (為什么是8000,因?yàn)槲覀兯愕氖呛撩?,原公式單位為?

那么就可以把代碼中的

IntStream.range(0, (int) (duration * 32)).forEach(x -> oldBytes.add((byte) 0));

修改為:

IntStream.range(0, (int) (duration * 128)).forEach(x -> oldBytes.add((byte) 0));

同時(shí)需要把頭文件的格式也調(diào)整一下:

byte[] header = buildWavHeader(pcmData.length, 16000, 1, 16);

修改為:

byte[] header = buildWavHeader(pcmData.length, 32000, 2, 16);

總結(jié)

當(dāng)然生成靜音的方法有很多,比如使用sox在ubuntu上一行命令就行。不過(guò)如果需要在工程化項(xiàng)目中,對(duì)原始音頻做靜音拼接組裝,那么你看懂了我上面的邏輯,就應(yīng)該知道如何實(shí)現(xiàn)了吧。只要讀取音頻中的數(shù)據(jù)包,然后往后面添加需要靜音時(shí)長(zhǎng)的靜音數(shù)據(jù)包,重新封裝頭,就可以得到了。

這里附上ubuntu上sox生成靜音的命令供大家參考.

sox -n -r 16000 -b 16 -c 1 -L silence.wav trim 0.0 5.000

以上就是Java實(shí)現(xiàn)生成自定義時(shí)長(zhǎng)的靜音音頻的詳細(xì)內(nèi)容,更多關(guān)于Java自定義靜音音頻的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 1秒鐘實(shí)現(xiàn)Springboot?替換/寫入?word文檔里面的文字、圖片功能

    1秒鐘實(shí)現(xiàn)Springboot?替換/寫入?word文檔里面的文字、圖片功能

    這篇文章主要介紹了Springboot?替換/寫入?word文檔里面的文字、圖片,1秒鐘實(shí)現(xiàn),本文結(jié)合示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-12-12
  • 基于CXF搭建webService的實(shí)例講解

    基于CXF搭建webService的實(shí)例講解

    下面小編就為大家?guī)?lái)一篇基于CXF搭建webService的實(shí)例講解。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-11-11
  • spring通過(guò)filter,Interceptor統(tǒng)一處理ResponseBody的返回值操作

    spring通過(guò)filter,Interceptor統(tǒng)一處理ResponseBody的返回值操作

    這篇文章主要介紹了spring通過(guò)filter,Interceptor統(tǒng)一處理ResponseBody的返回值操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-09-09
  • Spring MVC中異常處理的三種方式

    Spring MVC中異常處理的三種方式

    這篇文章主要給大家介紹了關(guān)于Spring MVC中異常處理的三種方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Spring MVC具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • 對(duì)ArrayList和LinkedList底層實(shí)現(xiàn)原理詳解

    對(duì)ArrayList和LinkedList底層實(shí)現(xiàn)原理詳解

    今天小編就為大家分享一篇對(duì)ArrayList和LinkedList底層實(shí)現(xiàn)原理詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-10-10
  • spring boot admin 搭建詳解

    spring boot admin 搭建詳解

    本篇文章主要介紹了spring boot admin 搭建詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-04-04
  • java驗(yàn)證碼組件kaptcha使用方法

    java驗(yàn)證碼組件kaptcha使用方法

    這篇文章主要介紹了java驗(yàn)證碼組件kaptcha使用方法,很不錯(cuò)的一個(gè)組件,可以在JAVA開發(fā)中使用,大家都試試吧
    2013-11-11
  • springmvc的@Validated注解使用

    springmvc的@Validated注解使用

    這篇文章主要介紹了springmvc的@Validated注解使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • SpringBoot使用Jwt處理跨域認(rèn)證問(wèn)題的教程詳解

    SpringBoot使用Jwt處理跨域認(rèn)證問(wèn)題的教程詳解

    這篇文章主要介紹了SpringBoot使用Jwt處理跨域認(rèn)證問(wèn)題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-06-06
  • Spring中屬性注入詳解

    Spring中屬性注入詳解

    這篇文章主要為大家詳細(xì)介紹了Spring中屬性注入,演示了int、String、數(shù)組、list等屬性的注入,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-10-10

最新評(píng)論