java sound sdk.

This commit is contained in:
Calvin 2021-09-10 14:27:12 +08:00
parent f6ef9bb786
commit 77bab9073e
12 changed files with 657 additions and 0 deletions

View File

@ -0,0 +1,70 @@
## 声音处理工具包
java常用声音工具包含
- 语音播放播放wav,mp3,flac,ape格式音频文件
- mp3 转 wav
- wav文件格式转换
- 截取部分wav文件可以设置起始终止时间
- wav文件合并两个合并成一个
## 运行例子 - AudioPlayerExample
运行成功后,命令行应该看到下面的信息:
并且能听到播放的声音。
```text
音频格式MPEG1L3
每秒播放帧数44100.0
总帧数:-1
音频时长(秒):-2.2675737E-5
```
## 运行例子 - MP3ToWAVExample
运行成功后,命令行应该看到下面的信息:
```text
...
File Format Type: MP3
File Format String: MP3 (.mp3) file, byte length: 387701, data format: MPEG1L3 44100.0 Hz, unknown bits per sample, stereo, unknown frame size, 38.28125 frames/second, , frame length: 371
File lenght: 387701
Frame length: 371
Channels: 2
Encoding: MPEG1L3
Frame Rate: 38.28125
Frame Size: -1
Sample Rate: 44100.0
Sample size (bits): -1
Big endian: true
Audio Format String: MPEG1L3 44100.0 Hz, unknown bits per sample, stereo, unknown frame size, 38.28125 frames/second,
Bytes Written: 854784
```
## 运行例子 - WavToWavExample
运行成功后,命令行应该看到下面的信息:
```text
File Format Type: MP3
File Format String: MP3 (.mp3) file, byte length: 385242, data format: MPEG1L3 44100.0 Hz, unknown bits per sample, stereo, unknown frame size, 38.28125 frames/second, , frame length: 369
File lenght: 385242
Frame length: 369
Channels: 2
Encoding: MPEG1L3
Frame Rate: 38.28125
Frame Size: -1
Sample Rate: 44100.0
Sample size (bits): -1
Big endian: true
Audio Format String: MPEG1L3 44100.0 Hz, unknown bits per sample, stereo, unknown frame size, 38.28125 frames/second,
Bytes Written: 847872
```
## 运行例子 - WaveChopExample
运行成功后,命令行应该看到下面的信息:
```text
[INFO ] - Source wave file: build/output/wav_converted.wav
[INFO ] - Wave Length: 9 seconds
[INFO ] - Wave chopped: build/output/wav_chop_result.wav
```
## 运行例子 - WavToWavExample
运行成功后,命令行应该看到下面的信息:
```text
[INFO ] - wavFile1: build/output/wav_converted.wav
[INFO ] - wavFile2: build/output/wav_converted.wav
[INFO ] - wav File appended: build/output/wav_appended.wav
```

View File

@ -0,0 +1,115 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Licensed to the Apache Software Foundation (ASF) under one
~ or more contributor license agreements. See the NOTICE file
~ distributed with this work for additional information
~ regarding copyright ownership. The ASF licenses this file
~ to you under the Apache License, Version 2.0 (the
~ "License"); you may not use this file except in compliance
~ with the License. You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing,
~ software distributed under the License is distributed on an
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
~ KIND, either express or implied. See the License for the
~ specific language governing permissions and limitations
~ under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>calvin</groupId>
<artifactId>sound-sdk</artifactId>
<version>0.1</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
<version>3.8.1</version>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.12.1</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>21.0</version>
</dependency>
<dependency>
<groupId>com.googlecode.soundlibs</groupId>
<artifactId>tritonus-share</artifactId>
<version>0.3.7.4</version>
</dependency>
<dependency>
<groupId>com.googlecode.soundlibs</groupId>
<artifactId>tritonus-all</artifactId>
<version>0.3.7.2</version>
</dependency>
<dependency>
<groupId>com.googlecode.soundlibs</groupId>
<artifactId>jlayer</artifactId>
<version>1.0.1.4</version>
</dependency>
<dependency>
<groupId>com.googlecode.soundlibs</groupId>
<artifactId>mp3spi</artifactId>
<version>1.9.5.4</version>
</dependency>
<dependency>
<groupId>com.googlecode.soundlibs</groupId>
<artifactId>jorbis</artifactId>
<version>0.0.17.4</version>
</dependency>
<dependency>
<groupId>com.googlecode.soundlibs</groupId>
<artifactId>vorbisspi</artifactId>
<version>1.0.3.3</version>
</dependency>
<dependency>
<groupId>com.googlecode.soundlibs</groupId>
<artifactId>basicplayer</artifactId>
<version>3.0.0.0</version>
</dependency>
<dependency>
<groupId>fr.delthas</groupId>
<artifactId>javamp3</artifactId>
<version>1.0.1</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="CheckStyle-IDEA-Module">
<option name="configuration">
<map />
</option>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="aias-jieba-lib-0.1.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-slf4j-impl:2.12.1" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.25" level="project" />
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-api:2.12.1" level="project" />
<orderEntry type="library" scope="RUNTIME" name="Maven: org.apache.logging.log4j:log4j-core:2.12.1" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.12.0" level="project" />
<orderEntry type="library" name="Maven: com.google.guava:guava:21.0" level="project" />
<orderEntry type="library" name="Maven: com.googlecode.soundlibs:tritonus-share:0.3.7.4" level="project" />
<orderEntry type="library" name="Maven: com.googlecode.soundlibs:tritonus-all:0.3.7.2" level="project" />
<orderEntry type="library" name="Maven: com.googlecode.soundlibs:jlayer:1.0.1.4" level="project" />
<orderEntry type="library" name="Maven: junit:junit:3.8.2" level="project" />
<orderEntry type="library" name="Maven: com.googlecode.soundlibs:mp3spi:1.9.5.4" level="project" />
<orderEntry type="library" name="Maven: com.googlecode.soundlibs:jorbis:0.0.17.4" level="project" />
<orderEntry type="library" name="Maven: com.googlecode.soundlibs:vorbisspi:1.0.3.3" level="project" />
<orderEntry type="library" name="Maven: com.googlecode.soundlibs:basicplayer:3.0.0.0" level="project" />
<orderEntry type="library" name="Maven: fr.delthas:javamp3:1.0.1" level="project" />
</component>
</module>

View File

@ -0,0 +1,70 @@
package me.calvin.example;
import javax.sound.sampled.*;
import java.io.File;
import java.io.IOException;
/**
* JAVA 播放wav,mp3,flac,ape格式音频文件
* @author calvin
* @mail 179209347@qq.com
* @website www.aias.top
*/
public class AudioPlayerExample {
public static void main(String[] args) {
final AudioPlayerExample player = new AudioPlayerExample();
player.play("src/test/resources/audio.mp3");
// player.play("build/output/converted.wav");
}
public void play(String filePath) {
AudioInputStream audioInputStream = null;
try {
audioInputStream = AudioSystem.getAudioInputStream(new File(filePath));
// 获取音频文件编码格式
AudioFormat audioFormat = audioInputStream.getFormat();
System.out.println("音频格式:" + audioFormat.getEncoding());
System.out.println("每秒播放帧数:" + audioFormat.getSampleRate());
System.out.println("总帧数:" + audioInputStream.getFrameLength());
System.out.println("音频时长(秒):" + audioInputStream.getFrameLength() / audioFormat.getSampleRate());
// 转换文件编码
if (audioFormat.getEncoding() != AudioFormat.Encoding.PCM_SIGNED) {
audioFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, audioFormat.getSampleRate(), 16, audioFormat.getChannels(), audioFormat.getChannels() * 2, audioFormat.getSampleRate(), false);
// 将数据流转换成指定编码
audioInputStream = AudioSystem.getAudioInputStream(audioFormat, audioInputStream);
}
// 打开输出设备
DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class, audioFormat, AudioSystem.NOT_SPECIFIED);
// 得到一个播放设备
SourceDataLine sourceDataLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo);
// 指定编码打开
sourceDataLine.open(audioFormat);
// 开始播放
sourceDataLine.start();
int bytesPerFrame = audioInputStream.getFormat().getFrameSize();
// 将流数据写入数据行,边写边播
int numBytes = 1024 * bytesPerFrame;
byte[] audioBytes = new byte[numBytes];
while (audioInputStream.read(audioBytes) != -1) {
sourceDataLine.write(audioBytes, 0, audioBytes.length);
}
sourceDataLine.drain();
sourceDataLine.stop();
sourceDataLine.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
audioInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

View File

@ -0,0 +1,51 @@
package me.calvin.example;
import me.calvin.example.utils.SoundUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import javax.sound.sampled.*;
/**
* JAVA mp3 wav
* @author calvin
* @mail 179209347@qq.com
* @website www.aias.top
*/
public class MP3ToWAVExample {
private static final Logger logger = LoggerFactory.getLogger(MP3ToWAVExample.class);
public static void main(String [] args){
try{
AudioFileFormat inputFileFormat = AudioSystem.getAudioFileFormat(new File("src/test/resources/audio.mp3"));
AudioInputStream ais = AudioSystem.getAudioInputStream(new File("src/test/resources/audio.mp3"));
AudioFormat audioFormat = ais.getFormat();
System.out.println("File Format Type: "+inputFileFormat.getType());
System.out.println("File Format String: "+inputFileFormat.toString());
System.out.println("File lenght: "+inputFileFormat.getByteLength());
System.out.println("Frame length: "+inputFileFormat.getFrameLength());
System.out.println("Channels: "+audioFormat.getChannels());
System.out.println("Encoding: "+audioFormat.getEncoding());
System.out.println("Frame Rate: "+audioFormat.getFrameRate());
System.out.println("Frame Size: "+audioFormat.getFrameSize());
System.out.println("Sample Rate: "+audioFormat.getSampleRate());
System.out.println("Sample size (bits): "+audioFormat.getSampleSizeInBits());
System.out.println("Big endian: "+audioFormat.isBigEndian());
System.out.println("Audio Format String: "+audioFormat.toString());
AudioInputStream encodedASI = SoundUtils.convertAsStream(ais, SoundUtils.WAV);
try{
int i = AudioSystem.write(encodedASI, AudioFileFormat.Type.WAVE, new File("build/output/converted.wav"));
System.out.println("Bytes Written: "+i);
}catch(Exception e){
e.printStackTrace();
}
}catch(Exception e){
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,25 @@
package me.calvin.example;
import me.calvin.example.utils.SoundUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* JAVA wav文件合并
* @author calvin
* @mail 179209347@qq.com
* @website www.aias.top
*/
public class WavAppenderExample {
private static final Logger logger = LoggerFactory.getLogger(WavAppenderExample.class);
public static void main(String[] args) {
String wavFile1 = "build/output/wav_converted.wav";
String wavFile2 = "build/output/wav_converted.wav";
String destinationFile = "build/output/wav_appended.wav";
logger.info("wavFile1: {}", wavFile1);
logger.info("wavFile2: {}", wavFile2);
SoundUtils.appendStream(wavFile1,wavFile2,destinationFile);
logger.info("wav File appended: {}", destinationFile);
}
}

View File

@ -0,0 +1,50 @@
package me.calvin.example;
import me.calvin.example.utils.SoundUtils;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import java.io.File;
/**
* JAVA wav文件格式转换
* @author calvin
* @mail 179209347@qq.com
* @website www.aias.top
*/
public class WavToWavExample {
public static void main(String [] args){
try{
AudioFileFormat inputFileFormat = AudioSystem.getAudioFileFormat(new File("src/test/resources/audio.wav"));
AudioInputStream ais = AudioSystem.getAudioInputStream(new File("src/test/resources/audio.wav"));
AudioFormat audioFormat = ais.getFormat();
System.out.println("File Format Type: "+inputFileFormat.getType());
System.out.println("File Format String: "+inputFileFormat.toString());
System.out.println("File lenght: "+inputFileFormat.getByteLength());
System.out.println("Frame length: "+inputFileFormat.getFrameLength());
System.out.println("Channels: "+audioFormat.getChannels());
System.out.println("Encoding: "+audioFormat.getEncoding());
System.out.println("Frame Rate: "+audioFormat.getFrameRate());
System.out.println("Frame Size: "+audioFormat.getFrameSize());
System.out.println("Sample Rate: "+audioFormat.getSampleRate());
System.out.println("Sample size (bits): "+audioFormat.getSampleSizeInBits());
System.out.println("Big endian: "+audioFormat.isBigEndian());
System.out.println("Audio Format String: "+audioFormat.toString());
AudioInputStream encodedASI = SoundUtils.convertAsStream(ais, SoundUtils.WAV);
try{
int i = AudioSystem.write(encodedASI, AudioFileFormat.Type.WAVE, new File("build/output/wav_converted.wav"));
System.out.println("Bytes Written: "+i);
}catch(Exception e){
e.printStackTrace();
}
}catch(Exception e){
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,33 @@
package me.calvin.example;
import me.calvin.example.utils.SoundUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
/**
* JAVA 截取部分wav文件
* @author calvin
* @mail 179209347@qq.com
* @website www.aias.top
*/
public class WaveChopExample {
private static final Logger logger = LoggerFactory.getLogger(WaveChopExample.class);
public static void main(String[] args) throws Exception {
WaveChopExample waveChop = new WaveChopExample();
waveChop.run();
}
public void run() throws Exception {
File sourceFile = new File("build/output/wav_converted.wav");
File chopResult = new File("build/output/wav_chop_result.wav");
int length = SoundUtils.getWavLengthSeconds(sourceFile);
logger.info("Source wave file: {}", sourceFile);
logger.info("Wave Length: {} seconds",length);
SoundUtils.createChop(sourceFile, chopResult, 0, 3);
logger.info("Wave chopped: {}", chopResult);
}
}

View File

@ -0,0 +1,189 @@
package me.calvin.example.utils;
import java.io.*;
import javax.sound.sampled.*;
import org.tritonus.share.sampled.AudioFileTypes;
import org.tritonus.share.sampled.Encodings;
/**
* Sound format conversion utility class
*/
public class SoundUtils {
// Audio type contants
public static final AudioType MP3 = new AudioType("MPEG1L3", "MP3", "mp3");
public static final AudioType WAV = new AudioType("ULAW", "WAVE", "wav");
private SoundUtils() {
}
/**
* Converts a byte array of sound data to the given audio type, also returned as a byte array.
*/
public static byte[] convertAsByteArray(byte[] source, AudioType targetType) {
try {
System.out.print("Converting byte array to AudioInputStream...");
AudioInputStream ais = toStream(source, targetType);
System.out.println("done.");
System.out.print("Converting stream to new audio format...");
ais = convertAsStream(ais, targetType);
System.out.println("done.");
System.out.print("Converting new stream to byte array...");
byte[] target = toByteArray(ais, targetType);
System.out.println("done.");
return target;
} catch (IOException ex) {
throw new RuntimeException("Exception during audio conversion", ex);
} catch (UnsupportedAudioFileException ex) {
throw new RuntimeException("Exception during audio conversion", ex);
}
}
/**
* Converts an InputStream of sound data to the given audio type, returned as a byte array.
*/
public static byte[] convertAsByteArray(InputStream is, AudioType targetType) {
try {
AudioInputStream ais = AudioSystem.getAudioInputStream(is);
ais = convertAsStream(ais, targetType);
byte[] bytes = toByteArray(ais, targetType);
return bytes;
} catch (IOException ex) {
throw new RuntimeException("Exception during audio conversion", ex);
} catch (UnsupportedAudioFileException ex) {
throw new RuntimeException("Exception during audio conversion", ex);
}
}
/**
* Converts an AudioInputStream to the indicated audio type, also returned as an AudioInputStream.
*/
public static AudioInputStream convertAsStream(AudioInputStream sourceStream, AudioType targetType) {
AudioFormat.Encoding targetEncoding = targetType.getEncoding();
AudioFormat sourceFormat = sourceStream.getFormat();
AudioInputStream targetStream = null;
if (!AudioSystem.isConversionSupported(targetEncoding, sourceFormat)) {
// Direct conversion not possible, trying with intermediate PCM format
AudioFormat intermediateFormat = new AudioFormat(
AudioFormat.Encoding.PCM_SIGNED,
sourceFormat.getSampleRate(),
16,
sourceFormat.getChannels(),
2 * sourceFormat.getChannels(), // frameSize
sourceFormat.getSampleRate(),
false);
if (AudioSystem.isConversionSupported(intermediateFormat, sourceFormat)) {
// Intermediate conversion is supported
sourceStream = AudioSystem.getAudioInputStream(intermediateFormat, sourceStream);
}
}
targetStream = AudioSystem.getAudioInputStream(targetEncoding, sourceStream);
if (targetStream == null) {
throw new RuntimeException("Audio conversion not supported");
}
return targetStream;
}
/**
* Converts a byte array to an AudioInputStream with the same audio format.
*/
private static AudioInputStream toStream(byte[] bytes, AudioType targetType)
throws IOException, UnsupportedAudioFileException {
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
AudioInputStream ais = AudioSystem.getAudioInputStream(bais);
return ais;
}
/**
* Converts an AudioInputStream to a byte array with the same audio format.
*/
private static byte[] toByteArray(AudioInputStream ais, AudioType targetType) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
AudioSystem.write(ais, targetType.getFileFormat(), baos);
return baos.toByteArray();
}
/**
* Append a wav file to another wav file
*/
public static void appendStream(String wavFile1, String wavFile2, String destinationFile) {
try (AudioInputStream clip1 = AudioSystem.getAudioInputStream(new File(wavFile1));
AudioInputStream clip2 = AudioSystem.getAudioInputStream(new File(wavFile2));
AudioInputStream appendedFiles =
new AudioInputStream(
new SequenceInputStream(clip1, clip2),
clip1.getFormat(),
clip1.getFrameLength() + clip2.getFrameLength())) {
AudioSystem.write(appendedFiles,
AudioFileFormat.Type.WAVE,
new File(destinationFile));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Get a wav file time length (seconds)
*/
public static int getWavLengthSeconds(File sourceFile) throws Exception {
try (AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(sourceFile)) {
AudioFormat format = audioInputStream.getFormat();
long audioFileLength = sourceFile.length();
int frameSize = format.getFrameSize();
float frameRate = format.getFrameRate();
float durationInSeconds = (audioFileLength / (frameSize * frameRate));
// downcast to int
return (int) durationInSeconds;
}
}
/**
* Create chop from a wav file
*/
public static void createChop(File sourceFile, File destinationFile, int startSecond, int secondsToCopy) {
try (AudioInputStream inputStream = AudioSystem.getAudioInputStream(sourceFile)) {
AudioFileFormat fileFormat = AudioSystem.getAudioFileFormat(sourceFile);
AudioFormat format = fileFormat.getFormat();
int bytesPerSecond = format.getFrameSize() * (int) format.getFrameRate();
inputStream.skip(startSecond * bytesPerSecond);
long framesOfAudioToCopy = secondsToCopy * (int) format.getFrameRate() / 4;
try (AudioInputStream shortenedStream = new AudioInputStream(inputStream, format, framesOfAudioToCopy)) {
AudioSystem.write(shortenedStream, fileFormat.getType(), destinationFile);
}
} catch (Exception e) {
System.out.println(e.toString());
}
}
/**
* Class representing an audio type, encapsulating an encoding and a file format.
*/
public static class AudioType {
private String encodingName;
private String typeName;
private String extension;
public AudioType(String encodingName, String typeName, String extension) {
this.encodingName = encodingName;
this.typeName = typeName;
this.extension = extension;
}
public AudioFormat.Encoding getEncoding() {
return Encodings.getEncoding(encodingName);
}
public AudioFileFormat.Type getFileFormat() {
return AudioFileTypes.getType(typeName, extension);
}
}
}

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
<Appenders>
<Console name="console" target="SYSTEM_OUT">
<PatternLayout
pattern="[%-5level] - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="info" additivity="false">
<AppenderRef ref="console"/>
</Root>
<Logger name="me.calvin" level="${sys:me.calvin.logging.level:-info}" additivity="false">
<AppenderRef ref="console"/>
</Logger>
</Loggers>
</Configuration>

Binary file not shown.

Binary file not shown.