Java 使用两个音频线程时出现音频故障
我使用一个线程绘制波形,另一个线程播放音频。唯一的问题是,我在播放时会出现音频口吃,这是因为解码音频过程: 音频编码器。解码音频(样本、数据包、偏移量) 以下是我的波形绘制课程:Java 使用两个音频线程时出现音频故障,java,audio,xuggler,Java,Audio,Xuggler,我使用一个线程绘制波形,另一个线程播放音频。唯一的问题是,我在播放时会出现音频口吃,这是因为解码音频过程: 音频编码器。解码音频(样本、数据包、偏移量) 以下是我的波形绘制课程: public class DrawWaveform extends Thread{ String f; int n; DrawWaveform(final String file, final int nstream) { this.setPriority(10);
public class DrawWaveform extends Thread{
String f;
int n;
DrawWaveform(final String file, final int nstream)
{
this.setPriority(10);
f = file;
n = nstream;
}
public void run() {
stopThread = false;
{
IContainer container = IContainer.make();
container.open(f, IContainer.Type.READ, null);
// query how many streams the call to open found
int numStreams = container.getNumStreams();
int count = 0;
IStreamCoder audioCoder = null;
int audioStreamId = -1;
for (int i = 0; i < numStreams; i++)
{
// Find the stream object
IStream stream = container.getStream(i);
// Get the pre-configured decoder that can decode this stream;
IStreamCoder coder = stream.getStreamCoder();
//si le premier élément est audio alors t = true sinon t = false
if (coder.getCodecType() == ICodec.Type.CODEC_TYPE_AUDIO)
{
if (count == n)
{
//on commence la lecture an plein milieu du son
//container.seekKeyFrame(i, dur/2, container.SEEK_FLAG_BYTE);
format = coder.getSampleFormat();
audioCoder = coder;
audioStreamId = i;
break;
}
count += 1;
}
}
if (audioCoder.open() < 0)
throw new RuntimeException("could not open audio decoder for container: "+f);
int sr = container.getStream(audioStreamId).getStreamCoder().getSampleRate();
zoomFactor = (int) Math.round(220.*sr/11630.);
long dur = container.getDuration();//en microsecondes
samples = new int[(int)(dur*sr/(1000*1000))];
//openJavaSound(audioCoder);
/*
* Now, we start walking through the container looking at each packet.
*/
IPacket packet = IPacket.make();
//on parcours tout le fichier f
while(container.readNextPacket(packet) >= 0 && !stopThread)
{
/*
* Now we have a packet, let's see if it belongs to our audio stream
*/
//on s'assure que le packet lu correspond au bon stream
if (packet.getStreamIndex() == audioStreamId)
{
/*
* We allocate a set of samples with the same number of channels as the
* coder tells us is in this buffer.
*
* We also pass in a buffer size (1024 in our example), although Xuggler
* will probably allocate more space than just the 1024 (it's not important why).
*/
IAudioSamples samples = IAudioSamples.make(1024, audioCoder.getChannels());
/*
* A packet can actually contain multiple sets of samples (or frames of samples
* in audio-decoding speak). So, we may need to call decode audio multiple
* times at different offsets in the packet's data. We capture that here.
*/
int offset = 0;
/*
* Keep going until we've processed all data
*/
while(offset < packet.getSize())
{
//if i remove this line, no more audio glitches
int bytesDecoded = audioCoder.decodeAudio(samples, packet, offset);
if (bytesDecoded < 0)
throw new RuntimeException("got error decoding audio in: " + f);
offset += bytesDecoded;
/*
* Some decoder will consume data in a packet, but will not be able to construct
* a full set of samples yet. Therefore you should always check if you
* got a complete set of samples from the decoder
*/
if (!stopThread)
if(samples.isComplete())
{
makeWaveform(samples);
currentPlayTime += samples.getNumSamples();
//System.out.println("max = "+48000*container.getDuration()/1000000 + " current = "+currentPlayTime);
}
}
}
else
{
/*
* This packet isn't part of our audio stream, so we just silently drop it.
*/
}
}
}
}
}
public类线程{
字符串f;
int n;
DrawWaveform(最终字符串文件,最终int nstream)
{
这是设置优先级(10);
f=文件;
n=n流;
}
公开募捐{
stopThread=false;
{
IContainer容器=IContainer.make();
container.open(f,IContainer.Type.READ,null);
//查询要打开的调用找到了多少流
int numStreams=container.getNumStreams();
整数计数=0;
IStreamCoder音频编码器=空;
int audioStreamId=-1;
for(int i=0;i=0&&!stopThread)
{
/*
*现在我们有了一个数据包,让我们看看它是否属于我们的音频流
*/
//关于s'quele包lu-au-bon流
if(packet.getStreamIndex()==audioStreamId)
{
/*
*我们分配一组样本,样本数量与
*编码器告诉我们它在这个缓冲区中。
*
*我们还传入一个缓冲区大小(在我们的示例中为1024),尽管Xuggler
*可能会分配比1024更多的空间(为什么不重要)。
*/
IAudioSamples samples=IAudioSamples.make(1024,audioCoder.getChannels());
/*
*一个数据包实际上可以包含多组样本(或样本帧)
*在音频解码中,我们可能需要调用decode audio multiple
*数据包数据中不同偏移量的时间。我们在这里捕获它。
*/
整数偏移=0;
/*
*继续,直到我们处理完所有数据
*/
while(偏移量
如果我删除所需的解码音频线路,我也会删除故障
我试图更改线程的优先级,但没有成功。我还试图改变缓冲区的大小,相同
那么,有没有办法避免这种情况
感谢大家检查一下:你确定是
解码音频
造成的(使用评测还是其他什么)?如果没有,如果你解码音频,但不绘制波形会发生什么