0
点赞
收藏
分享

微信扫一扫

Java合并(连接)多个音频

秦瑟读书 2022-08-18 阅读 29


​​java sound resource​​

合并的说法有歧义,为了方便大家搜索到这里,所以用这个标题,实际上是连接(concat),可以理解为字符串concat方法所指定的含义。

AudioConcat.java源码

*    AudioConcat.java
*
* This file is part of jsresources.org
*/

/*
* Copyright (c) 1999 - 2001 by Matthias Pfisterer
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/*
|<--- this code is formatted to fit into 80 columns --->|
*/

import gnu.getopt.Getopt;

import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/* If the compilation fails because this class is not available,
get gnu.getopt from the URL given in the comment below.
*/


// TODO: the name AudioConcat is no longer appropriate. There should be a name that is neutral to concat/mix.

/** <titleabbrev>AudioConcat</titleabbrev>
<title>Concatenating or mixing audio files</title>

<formalpara><title>Purpose</title>
<para>This program reads multiple audio files and
writes a single one either
containing the data of all the other
files in order (concatenation mode, option <option>-c</option>)
or containing a mixdown of all the other files
(mixing mode, option <option>-m</option>).
For concatenation, the input files must have the same audio
format. They need not have the same file type.</para>
</formalpara>

<formalpara><title>Usage</title>
<para>
<cmdsynopsis>
<command>java AudioConcat</command>
<arg choice="plain"><option>-h</option></arg>
</cmdsynopsis>
<cmdsynopsis>
<command>java AudioConcat</command>
<arg choice="opt"><option>-D</option></arg>
<group choice="plain">
<arg><option>-c</option></arg>
<arg><option>-m</option></arg>
</group>
<arg choice="plain"><option>-o <replaceable>outputfile</replaceable></option></arg>
<arg choice="plain" rep="repeat"><replaceable>inputfile</replaceable></arg>
</cmdsynopsis>
</para>
</formalpara>

<formalpara><title>Parameters</title>
<variablelist>
<varlistentry>
<term><option>-c</option></term>
<listitem><para>selects concatenation mode</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-m</option></term>
<listitem><para>selects mixing mode</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-o <replaceable>outputfile</replaceable></option></term>
<listitem><para>The filename of the output file</para></listitem>
</varlistentry>
<varlistentry>
<term><replaceable>inputfile</replaceable></term>
<listitem><para>the name(s) of input file(s)</para></listitem>
</varlistentry>
</variablelist>
</formalpara>

<formalpara><title>Bugs, limitations</title>
<para>
This program is not well-tested. Output is always a WAV
file. Future versions should be able to convert
different audio formats to a dedicated target format.
</para></formalpara>

<formalpara><title>Source code</title>
<para>
<ulink url="AudioConcat.java.html">AudioConcat.java</ulink>,
<ulink url="SequenceAudioInputStream.java.html">SequenceAudioInputStream.java</ulink>,
<ulink url="MixingAudioInputStream.java.html">MixingAudioInputStream.java</ulink>,
<ulink url="http://www.urbanophile.com/arenn/hacking/download.html">gnu.getopt.Getopt</ulink>
</para>
</formalpara>

*/
public class AudioConcat
{
private static final int MODE_NONE = 0;
private static final int MODE_MIXING = 1;
private static final int MODE_CONCATENATION = 2;

/** Flag for debugging messages.
* If true, some messages are dumped to the console
* during operation.
*/
private static boolean DEBUG = false;



public static void main(String[] args)
{
/** Mode of operation.
Determines what to do with the input files:
either mixing or concatenation.
*/
int nMode = MODE_NONE;
String strOutputFilename = null;
AudioFormat audioFormat = null;
List audioInputStreamList = new ArrayList();

// int nExternalBufferSize = DEFAULT_EXTERNAL_BUFFER_SIZE;
// int nInternalBufferSize = AudioSystem.NOT_SPECIFIED;


/*
* Parsing of command-line options takes place...
*/
Getopt g = new Getopt("AudioConcat", args, "hDcmo:");
int c;
while ((c = g.getopt()) != -1)
{
switch (c)
{
case 'h':
printUsageAndExit();

case 'o':
strOutputFilename = g.getOptarg();
if (DEBUG) { out("AudioConcat.main(): output filename: " + strOutputFilename); }
break;

case 'c':
nMode = MODE_CONCATENATION;
break;

case 'm':
nMode = MODE_MIXING;
break;

case 'D':
DEBUG = true;
break;

case '?':
printUsageAndExit();

default:
out("AudioConcat.main(): getopt() returned " + c);
break;
}
}

/*
* All remaining arguments are assumed to be filenames of
* soundfiles we want to play.
*/
String strFilename = null;
for (int i = g.getOptind(); i < args.length; i++)
{
strFilename = args[i];
File soundFile = new File(strFilename);

/*
* We have to read in the sound file.
*/
AudioInputStream audioInputStream = null;
try
{
audioInputStream = AudioSystem.getAudioInputStream(soundFile);
}
catch (Exception e)
{
/*
* In case of an exception, we dump the exception
* including the stack trace to the console output.
* Then, we exit the program.
*/
e.printStackTrace();
System.exit(1);
}
AudioFormat format = audioInputStream.getFormat();
/*
The first input file determines the audio format. This stream's
AudioFormat is stored. All other streams are checked against
this format.
*/
if (audioFormat == null)
{
audioFormat = format;
if (DEBUG) { out("AudioConcat.main(): format: " + audioFormat); }
}
else if ( ! audioFormat.matches(format))
{
// TODO: try to convert
out("AudioConcat.main(): WARNING: AudioFormats don't match");
out("AudioConcat.main(): master format: " + audioFormat);
out("AudioConcat.main(): this format: " + format);
}
audioInputStreamList.add(audioInputStream);
}

if (audioFormat == null)
{
out("No input filenames!");
printUsageAndExit();
}
AudioInputStream audioInputStream = null;
switch (nMode)
{
case MODE_CONCATENATION:
audioInputStream = new SequenceAudioInputStream(audioFormat, audioInputStreamList);
break;

case MODE_MIXING:
audioInputStream = new MixingAudioInputStream(audioFormat, audioInputStreamList);
break;

default:
out("you have to specify a mode (either -m or -c).");
printUsageAndExit();
}

if (strOutputFilename == null)
{
out("you have to specify an output filename (using -o <filename>).");
printUsageAndExit();
}
File outputFile = new File(strOutputFilename);
try
{
AudioSystem.write(audioInputStream, AudioFileFormat.Type.WAVE, outputFile);
}
catch (IOException e)
{
e.printStackTrace();
}

if (DEBUG) { out("AudioConcat.main(): before exit"); }
System.exit(0);
}



private static void printUsageAndExit()
{
out("AudioConcat: usage:");
out("\tjava AudioConcat -h");
out("\tjava AudioConcat [-D] -c|-m -o <outputfile> <inputfile> ...");
System.exit(1);
}



private static void out(String strMessage)
{
System.out.println(strMessage);
}
}



/*** AudioConcat.java ***/

食用方法(从main方法中拷贝出代码来测试):

import org.junit.Test;

import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.TreeSet;

public class TestConcatAudioStream {

private static final int MODE_MIXING = 1;
private static final int MODE_CONCATENATION = 2;
/** Flag for debugging messages.
* If true, some messages are dumped to the console
* during operation.
*/
private static boolean DEBUG = true;

private static void out(String strMessage)
{
System.out.println(strMessage);
}

@Test
public void testMultiReSampling2() throws IOException, UnsupportedAudioFileException {
TreeSet<String> orderedFileNames = getOrderedSeqFileNames();
Iterator<String> it = orderedFileNames.iterator();

ByteOutputStream out = new ByteOutputStream();

while (it.hasNext())
{
String fileName = it.next();

String _16kFileName = fileName.substring(0, fileName.lastIndexOf(".")).concat("_16k.wav");
convert(fileName,_16kFileName);
RandomAccessFile raf = new RandomAccessFile(_16kFileName, "r");
raf.skipBytes(44);
byte buff[] = new byte[(int) (raf.length()-44)];
raf.read(buff);
out.write(buff);
}
WavFileGenerator generator = new WavFileGenerator(16000,16);
//AudioStreamHelper.saveToFile("e:/asset/sampleRateConverter_16k.wav",out.getBytes());
generator.saveFile("e:/asset/sampleRateConverter_16k.wav",out.getBytes());
}

@Test
public void testMultiReSampling() throws IOException {
TreeSet<String> orderedFileNames = getOrderedSeqFileNames();
Iterator<String> it = orderedFileNames.iterator();

ByteOutputStream out = new ByteOutputStream();

while (it.hasNext())
{
String fileName = it.next();
byte[] bytes = Files.readAllBytes(Paths.get(fileName));
byte[] resampled = AudioStreamHelper.reSampling2PCM(bytes);
out.write(resampled);
}
StdAudio.play(out.toByteArray());
}


void convert(String srcFile,String trgtFile) throws IOException, UnsupportedAudioFileException {
float fTargetSampleRate =16000.0f;
if (DEBUG) { out("target sample rate: " + fTargetSampleRate); }
File sourceFile = new File(srcFile);
File targetFile = new File(trgtFile);

/* We try to use the same audio file type for the target
file as the source file. So we first have to find
out about the source file's properties.
*/
AudioFileFormat sourceFileFormat = AudioSystem.getAudioFileFormat(sourceFile);
AudioFileFormat.Type targetFileType = sourceFileFormat.getType();

/* Here, we are reading the source file.
*/
AudioInputStream sourceStream = null;
sourceStream = AudioSystem.getAudioInputStream(sourceFile);
if (sourceStream == null)
{
out("cannot open source audio file: " + sourceFile);
System.exit(1);
}
AudioFormat sourceFormat = sourceStream.getFormat();
if (DEBUG) { out("source format: " + sourceFormat); }

/* Currently, the only known and working sample rate
converter for Java Sound requires that the encoding
of the source stream is PCM (signed or unsigned).
So as a measure of convenience, we check if this
holds here.
*/
AudioFormat.Encoding encoding = sourceFormat.getEncoding();
if (! AudioCommon.isPcm(encoding))
{
out("encoding of source audio data is not PCM; conversion not possible");
System.exit(1);
}

/* Since we now know that we are dealing with PCM, we know
that the frame rate is the same as the sample rate.
*/
float fTargetFrameRate = fTargetSampleRate;

/* Here, we are constructing the desired format of the
audio data (as the result of the conversion should be).
We take over all values besides the sample/frame rate.
*/

AudioFormat targetFormat = new AudioFormat(
sourceFormat.getEncoding(),
fTargetSampleRate,
sourceFormat.getSampleSizeInBits(),
sourceFormat.getChannels(),
sourceFormat.getFrameSize(),
fTargetFrameRate,
sourceFormat.isBigEndian());

if (DEBUG) { out("desired target format: " + targetFormat); }

/* Now, the conversion takes place.
*/
AudioInputStream targetStream = AudioSystem.getAudioInputStream(targetFormat, sourceStream);
if (DEBUG) { out("targetStream: " + targetStream); }

/* And finally, we are trying to write the converted audio
data to a new file.
*/
int nWrittenBytes = 0;
nWrittenBytes = AudioSystem.write(targetStream, targetFileType, targetFile);
if (DEBUG) { out("Written bytes: " + nWrittenBytes); }
}

@Test
public void testMultiReSamplingUsingStreamConvert() throws IOException {
TreeSet<String> orderedFileNames = getOrderedSeqFileNames();
Iterator<String> it = orderedFileNames.iterator();

ByteOutputStream out = new ByteOutputStream();

while (it.hasNext())
{
String fileName = it.next();
byte[] bytes = Files.readAllBytes(Paths.get(fileName));

byte[] resampled = AudioStreamHelper.reSampling2PCM(bytes);
out.write(resampled);
}
StdAudio.play(out.toByteArray());
}

@Test
public void test()
{

/** Mode of operation.
Determines what to do with the input files:
either mixing or concatenation.
*/
int nMode = MODE_CONCATENATION;
String strOutputFilename = "e:\\asset\\48k_concatStream.wav";
AudioFormat audioFormat = null;
List audioInputStreamList = new ArrayList();

/*
* All remaining arguments are assumed to be filenames of
* soundfiles we want to play.
*/

String strFilename = null;

int size = getOrderedSeqFileNames().size();

Iterator<String> it = getOrderedSeqFileNames().iterator();
while (it.hasNext()){
//for (int i = 0; i < size; i++)
//{
strFilename = it.next();
File soundFile = new File(strFilename);

/*
* We have to read in the sound file.
*/
AudioInputStream audioInputStream = null;
try
{
audioInputStream = AudioSystem.getAudioInputStream(soundFile);
}
catch (Exception e)
{
/*
* In case of an exception, we dump the exception
* including the stack trace to the console output.
* Then, we exit the program.
*/
e.printStackTrace();
System.exit(1);
}
AudioFormat format = audioInputStream.getFormat();
/*
The first input file determines the audio format. This stream's
AudioFormat is stored. All other streams are checked against
this format.
*/
if (audioFormat == null)
{
audioFormat = format;
System.out.println("AudioConcat.main(): format: " + audioFormat);
}
else if ( ! audioFormat.matches(format))
{
// TODO: try to convert
System.out.println("AudioConcat.main(): WARNING: AudioFormats don't match");
System.out.println("AudioConcat.main(): master format: " + audioFormat);
System.out.println("AudioConcat.main(): this format: " + format);
}
audioInputStreamList.add(audioInputStream);
}

if (audioFormat == null)
{
System.out.println("No input filenames!");

}
AudioInputStream audioInputStream = null;
switch (nMode)
{
case MODE_CONCATENATION:
audioInputStream = new SequenceAudioInputStream(audioFormat, audioInputStreamList);
break;

case MODE_MIXING:
audioInputStream = new MixingAudioInputStream(audioFormat, audioInputStreamList);
break;

default:
System.out.println("you have to specify a mode (either -m or -c).");
}

if (strOutputFilename == null)
{
System.out.println("you have to specify an output filename (using -o <filename>).");

}
File outputFile = new File(strOutputFilename);
try
{
AudioSystem.write(audioInputStream, AudioFileFormat.Type.WAVE, outputFile);
}
catch (IOException e)
{
e.printStackTrace();
}
}


public TreeSet<String> getOrderedSeqFileNames()
{
try (DirectoryStream<Path> stream = Files.newDirectoryStream(Paths.get("E:\\asset"), "*.wav")) {

TreeSet<String> treeSet = new TreeSet<>();
Iterator<Path> it = stream.iterator();


while (it.hasNext()) {
Path path = it.next();
String filename = path.getFileName().toString();
if (filename.matches("\\d{13}\\.wav") && Files.size(path) > 0) {
treeSet.add(path.toString());
}
}
return treeSet;
}catch (Exception e)
{}
return null;
}
}

 

本地文件如下:

Java合并(连接)多个音频_音频

 

 

 

testMultiReSampling2输出结果

Java合并(连接)多个音频_java_02

中间生成文件

Java合并(连接)多个音频_html_03

 

 

 

 

 多个文件合成的文件

Java合并(连接)多个音频_html_04

 

 

 

Java合并(连接)多个音频_ide_05

 

举报

相关推荐

0 条评论