求一个简单java播放wav音频程序

求一个简单java播放wav音频程序,第1张

/

播放音乐

@param mp3Path

@param repeat

/

public static void playSound(final String mp3Path, final int repeat) {

new Thread(new Runnable() {

@Override

public void run() {

if (mp3PathendsWith("mp3")) {

// TODO Auto-generated method stub

MP3Player mp3 = new MP3Player(mp3Path);

int ccc = 0;

while (ccc < repeat) {

try {

Threadsleep(1000);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

eprintStackTrace();

}

ccc++;

mp3play();

}

} else {

try {

// wav 文件放在java project 下面

//SystemgetProperty("userdir") + Fileseparator+ "ringwav"

Systemoutprintln(mp3Path);

FileInputStream fileau = new FileInputStream(

mp3Path);

AudioStream as = new AudioStream(fileau);

int ccc = 0;

while (ccc < repeat) {

try {

Threadsleep(1000);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

eprintStackTrace();

}

ccc++;

AudioPlayerplayerstart(as);

}

} catch (Exception e) {

eprintStackTrace();

}

}

}

})start();

}

sun audio jar下载 需要自己下载

thisgetClass()getResource是得到当前对象对应的类文件(class)所在的目录下的文件。所以通过thisgetClass()getResource去获得C盘中的数据是获取不到的。

像C:\\loginwav这样的绝对路劲,你可以这样来获取:

URL url = new File("C:\\loginwav")toURI()toURL();

补充:

这个要看你的Pan这个类编译成的class文件在什么地方。thisgetClass()getResource()是相对于Panclass这个类文件的文件来说的,如果loginwav和Panclass同一目录下,那么thisgetClass()getResource("loginwav")就能获取到,如果loginwav是在Panclass的下一级目录music下,那么就是

thisgetClass()getResource("music/loginwav")了。

像这样的根据ClassLoader来获取资源的方式,应该不能查找上一级目录。如:

thisgetClass()getResource("/aa");这样好像是不行的。所以如果要取相对路径,那么要么就把loginwav和Panclass文件放在同一目录,要么就把loginwav放在Panclass的下一级目录。

如果还有什么不清楚,可以再说出来。我再补充。

Tomcat 是一个 Java Servlet 容器,通常用于部署和运行 Java Web 应用程序。如果您需要在 Tomcat 上处理音频文件,可以使用 Java 音频库和相关 API 来实现。

在 Java 中,处理音频文件可以使用 Java 音频库 (Java Sound API)。您可以使用 Java 音频库来读取和播放各种音频格式,包括 WAV 格式。以下是一个使用 Java 音频库读取 WAV 文件的示例代码:import javaxsoundsampledAudioInputStream;

import javaxsoundsampledAudioSystem;

import javaxsoundsampledClip;

import javaxsoundsampledDataLine;

import javaxsoundsampledLineUnavailableException;

import javaioFile;

import javaioIOException;

public class AudioPlayer {

public static void main(String[] args) {

try {

// 打开音频文件

AudioInputStream audioInputStream = AudioSystemgetAudioInputStream(new File("audiowav"));

DataLineInfo info = new DataLineInfo(Clipclass, audioInputStreamgetFormat());

Clip clip = (Clip) AudioSystemgetLine(info);

// 播放音频文件

clipopen(audioInputStream);

clipstart();

// 等待音频播放完成

while (!clipisRunning())

Threadsleep(10);

while (clipisRunning())

Threadsleep(10);

// 关闭音频文件

clipclose();

audioInputStreamclose();

} catch (LineUnavailableException e) {

eprintStackTrace();

} catch (IOException e) {

eprintStackTrace();

} catch (Exception e) {

eprintStackTrace();

}

}

}

这个示例代码将读取名为 "audiowav" 的 WAV 文件并将其播放。您可以根据自己的需要修改代码,例如将其嵌入到 Web 应用程序中以实现通过 Tomcat 来访问和播放音频文件。

Java中可以通过AudioClip类来实现音乐播放,循环等 *** 作。AudioClip支持的音乐格式有wav、mid、AIFF、AU、RMF,但是格式要求相当严格。我用AudioClip播放我自己录的一段wav文件就没有声音,让我纠结了很久,最后才发现我的wav文件内容没有写文件尾,对于格式要求严格的AudioClip而言是无法识别的(这个问题困扰了我整晚)。

AudioCLip主要的方法有:play()播放依次声音;loop()循环播放音乐;stop()停止播放。

做法一:

InputStream is =null;

AudioStream as = null ;

is = getClass()getResourceAsStream("awav");

try {

as = new AudioStream(is);

} catch (IOException e) {}

AudioPlayerplayerstart(as);

此方法将音乐文件放入流中在播放,仅限于Java Application,容易报错,空指针异常,或者是流异常,不推荐。

做法二:

String music = "awav";

AudioClip clip = AppletnewAudioClip(getClass()getResource(music));

次方法在Applet中运行没有问题,但是Application中getclass()会返回空指针,导致失败。

推荐做法:

private URL url;

private AudioClip ac;

File f1 = new File("C:/3wav");

try {

url= f1toURL();

} catch (MalformedURLException e) {

// TODO Auto-generated catch block

eprintStackTrace();

}

ac= AppletnewAudioClip(cb1);

acplay();

如果你已经成功地了解了关于AudioTrack的一些话题,那么你可能享受它带来的好处,例如低延迟(在STATIC(静态)模式),能够生成流式音频(在STREAM(流)模式)以及在播放之前,就能够访问和修改原始声音数据。

不过,现在的问题是如何从源获取数据。许多应用需要使用的AudioTrack并不能简单的生成PCM音频(一个例子,比如Ethereal Dialpad或者其他类似的App)。你可能需要从文件源去加载数据,例如WAV或MP3文件。

不要期望使用MediaPlayer,去解码WAV文件和MP3音频。虽然MediaPlayer播放这些文件非常好,但是其播放逻辑完全在Native层,同时并没有为我们提供额外选项,允许我们使用其他解码器实现我们的目的。因此,我们必须从手动地从音频文件进行解码出PCM。

在这篇文章中,将会讨论WAV格式文件。而在下一课中,我们将会更进一步,讨论如何从MP3文件读取音频。

背景知识: 一些数字音频术语

如果你的App不是专门为数字音频设计,那么在继续我们的讨论之前,你可能需要先了解一些基本的缩略语。别担心,都很简单,我们不需要对此做深入挖掘。

PCM(脉冲调制方式) – 实现一个物理音频信号变成数字化最简单方法。基本原理就是信号变成了一个数字阵列,而其中每个数字代表的是声音在特定的时间瞬间的电平也可以说是能量(振幅)。(如果这种解释在科学上可能不会很准确,那我就只能说声抱歉了)。信不信由你,你可以使用这种方法表示任何复杂的声音,而且回放出来也非常精准。在这里,我们将只会谈到线性PCM。在线性PCM中,其中阵列中的每个数字都是原始声音振幅的线性表示。在某些情况下,对数映射能够更好地表示原来的声音幅度比例情况 – 但是我们不会讨论那些情况。

Sampling rate(采样率):- 每秒你的数字声音有多少样本(声音幅度用数字表示)。样本越多,你能得到声音质量越好。目前在消费类音频系统目前使用的采样率通常是22050,44100和48000Hz/s。

每个样品分辨率/采样大小/位 – 定义表示振幅数字的大小和格式。例如,如果您使用的是8位整数,你只能表达出256级的幅度,所以原来的物理波形将被简化为256个离散电平,与此同时,你将失去一些声音精度也可以说是质量。如果你使用16位,那么声音质量变得更好。事实上,大部分时间你可能会使用16位音频。其他选项包括24位,32位(这些都是Android现在不支持的),或是使用浮点数。

声道 – 既可以是单声道,也可以是立体声(2个声道),或者更多声道(但是Android不支持)。如果你想要有立体声,你需要有立体声音频,就必须要在每个声道都需要有一个独立的PCM数组,相应的信息量也会翻倍。

上述定义也有助于你理解特定的格式和长度的音频缓冲区的数据量,以便提前预备缓冲区。也就是你需要一个缓冲区,以用于存储5秒长度以44100Hz采样率的立体声16-bit线性PCM数据。数据计算公式如下所示:

5 sec 44100 samples per sec 2 bytes per sample 2 channels = 882,000 bytes

这一数额所需的内存可能会让初学者感到惊讶,因为当你往你的磁盘上存储的音频时,一个MP3文件,一个880KB的文件就可以容纳以相同的采样率和分辨率1分钟时长的音轨。这是为什么呢?因为先进的格式,比如MP3格式。因为我们大脑无法分辨识别出一些音频的内容,所以使用了很多复杂的方式在压缩的过程中去掉了这些内容。然而,大多数低等级的音频API,包括Android的AudioTrack只能接受线性PCM。这就是为什么如果我们不能把整个样品都放在内存中,我们需要将要处理的数据流,循环缓冲区和其他聪明的方式来使用音频API。

希望这样的解释并没有让你产生困惑,现在让我们继续来实际做一些与Android上的数字音频有关的工作吧!

WAV文件格式

我们的目标是用一个InputStream,由其从一个WAV文件加载PCM数据,来提供原始字节数据。然后我们就可以将原始的PCM数据直接推送到使用已经正确的配置好了的AudioTrackwrite,通过使用AudioTrackwrite()这个API。

WAV文件包含一个文件头和具体数据会。我们需要读取文件头以知道诸如采样速率,分辨率等信息。另外,我们通过文件头,也可以知道此格式是否支持。WAV可以封装成多种格式,我们无法全部支持。也许,只是合理的采样率,分辨率和通道的线性PCM格式。

WAV格式的细节在互联网上都可以找到,你仅仅需要在Google上搜索下。但是,遗憾的是,我并没有搜索到一个很好的Java库来读取WAV文件,而且可以移植到Android下。因此,我自己写了一些简单的代码。

下面这个方法就是如何读取一个WAV文件的头部:

private static final String RIFF_HEADER = "RIFF";

private static final String WAVE_HEADER = "WAVE";

private static final String FMT_HEADER = "fmt ";

private static final String DATA_HEADER = "data";

private static final int HEADER_SIZE = 44;

private static final String CHARSET = "ASCII";

/ /

public static WavInfo readHeader(InputStream wavStream) throws IOException,

DecoderException {

ByteBuffer buffer = ByteBufferallocate(HEADER_SIZE);

bufferorder(ByteOrderLITTLE_ENDIAN);

wavStreamread(bufferarray(), bufferarrayOffset(), buffercapacity());

bufferrewind();

bufferposition(bufferposition() + 20);

int format = buffergetShort();

checkFormat(format == 1, "Unsupported encoding: " + format); // 1 means

// Linear

// PCM

int channels = buffergetShort();

checkFormat(channels == 1 || channels == 2, "Unsupported channels: "

+ channels);

int rate = buffergetInt();

checkFormat(rate <= 48000 && rate >= 11025, "Unsupported rate: " + rate);

bufferposition(bufferposition() + 6);

int bits = buffergetShort();

checkFormat(bits == 16, "Unsupported bits: " + bits);

int dataSize = 0;

while (buffergetInt() != 0x61746164) { // "data" marker

Logd(TAG, "Skipping non-data chunk");

int size = buffergetInt();

wavStreamskip(size);

bufferrewind();

wavStreamread(bufferarray(), bufferarrayOffset(), 8);

bufferrewind();

}

dataSize = buffergetInt();

checkFormat(dataSize > 0, "wrong datasize: " + dataSize);

return new WavInfo(new FormatSpec(rate, channels == 2), dataSize);

}

上面的代码中,缺少的部分应该是显而易见的。正如你所看到的,仅仅支持16位,但在你可以修改代码以支持8位(AudioTrack不支持任何其他分辨率的)。

下面这个方法,则是用来读取文件剩余的部分 – 音频数据。

public static byte[] readWavPcm(WavInfo info, InputStream stream)

throws IOException {

byte[] data = new byte[infogetDataSize()];

streamread(data, 0, datalength);

return data;

}

我们读取的WavInfo结构体,包含采样率,分辨率和声道数已经足够让我们去播放我们读取的音频了。

如果我们不需要将全部音频数据一次性放入内存中,我们可以使用一个InputStream,一点一点地读取。

将PCM传入AudioTrack

我们现在面临2种情况,新建一个适合这种格式的AudioTrack,或者使用一个已存在的AudioTrack,但是可能和我们WAV音频数据的格式不一致。

在第一种情况,事情就很简单了,我们仅仅需要使用AudioTrack构造器构造一个我们已经从WAV头部对应的即可。

第二种情况,我们就需要将我们的音频变成AudioTrack需要的目标格式。我们需要做一下几种转换方式:

如果采样率不同,要么丢弃或复制一个样本以便和目标速率相匹配。如果分辨率是不同的,将源信号分辨率映射到目标分辨率,从16位到8位,反之亦然。如果信道不同,我们要么将立体声声道混合成一个单声道或重复单声道的数据把它变成准立体声。(请考虑将这些算法的实现放在Native层,因为Native层在做这类处理有很大的优势。)

在其他情况下,我们已经确定格式已经匹配。我们使用AudioTrackwrite()写入缓冲区,以便实现回放。

记住,如果你使用静态模式,你需要在play()之前,新建一个包含准确的缓冲区大小的AudioTrack ,同时写入write()音频数据。而在流模式下,我们可以先使用AudioTrack的play(),然后在使用write()写入数据部分

import javaappletApplet;

import javaappletAudioClip;

import javanetMalformedURLException;

public class MusicAudioClip {

AudioClip clip = null;

public AudioClip getAudioClip() {

return thisclip;

}

public void setAudioClip(AudioClip clip) {

thisclip = clip;

}

public void play() {//播放

if (getAudioClip() != null) {

getAudioClip()play();

}

}

public void loop() {//循环

if (getAudioClip() != null) {

getAudioClip()loop();

}

}

public void stop() {//停止

if (getAudioClip() != null) {

getAudioClip()stop();

}

}

public static void main(String[] args) {

MusicAudioClip mac = new MusicAudioClip();

try {

macsetAudioClip(Applet

newAudioClip((new javaioFile("music\\0wav"))toURL()));//填写你自己的文件路径

} catch (MalformedURLException e) {

eprintStackTrace();

}

macloop();//循环播放

}

}

以上就是关于求一个简单java播放wav音频程序全部的内容,包括:求一个简单java播放wav音频程序、JAVA中获取资源问题 this.getClass().getResource("C:\\login.wav");、tomcat反复wav文件等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/9877984.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-02
下一篇2023-05-02

发表评论

登录后才能评论

评论列表(0条)

    保存