0
音声波形のリペイント
初めて質問させて頂きます。
音声ファイルを取得し、その音声波形を1秒ごとにパネルに表示させるというプログラムを作ってみたのですが
再生させると画面が固まってしまい、波形の表示が出来ません。
しかし、SampleWaveLineクラスのstartメソッドの「while(nowPlaying)」と書いてある1行を消し
再生ボタンを押すと、1秒だけ波形が表示されます。
これを再生中に連続して表示させるにはどうしたらよいでしょうか。
お手数ですが、ご回答宜しくお願い致します。
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import javax.sound.sampled.*;
public class SampleWaveLine extends JFrame
{
WavePanel wavePanel=new WavePanel();
private JPanel pn, pn2;
private Container cnt;
private JButton bt, bt2, bt3;
protected boolean nowPlaying=false;
File file;
AudioInputStream ais;
AudioFormat format;
DataLine.Info info;
SourceDataLine line;
public static void main(String[] args)
{
new SampleWaveLine();
}
public SampleWaveLine()
{
pn = new JPanel();
pn2 = new JPanel();
cnt = getContentPane();
bt = new JButton("取得");
bt2 = new JButton("再生");
bt3 = new JButton("停止");
pn.setLayout(new BorderLayout());
pn2.setLayout(new BorderLayout());
pn.add(wavePanel, BorderLayout.CENTER);
pn2.add(bt, BorderLayout.WEST);
pn2.add(bt2, BorderLayout.CENTER);
pn2.add(bt3, BorderLayout.EAST);
cnt.setLayout(new BorderLayout());
cnt.add(pn, BorderLayout.CENTER);
cnt.add(pn2, BorderLayout.NORTH);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(900,100,300,200);
setVisible(true);
bt.addActionListener(new SampleActionListener());
bt2.addActionListener(new SampleActionListener());
bt3.addActionListener(new SampleActionListener());
}
public void get()
{
try{
file = new File("001.wav");
ais = AudioSystem.getAudioInputStream(file);
format = ais.getFormat();
info = new DataLine.Info(SourceDataLine.class,format);
line = (SourceDataLine) AudioSystem.getLine(info);
}
catch(Exception e)
{
e.printStackTrace();
}
}
public void start()
{
try
{
line.open(format);
line.start();
nowPlaying=true;
while(nowPlaying)
OneSecondRead(ais,line,format);
}
catch(Exception ek)
{
}
}
public void stop()
{
line.drain();
line.close();
repaint();
}
private boolean OneSecondRead(AudioInputStream in,SourceDataLine dl,AudioFormat af)throws Exception
{
if(!nowPlaying)return false;
int readedSize;
int size=(int)af.getSampleRate()*af.getFrameSize();
byte[] data=new byte[size];
readedSize=in.read(data);
if(readedSize==-1)return false;
dl.write(data, 0, readedSize);
wavePanel.display(getIntFromFrameByte(data,af,true));
return true;
}
private int[] getIntFromFrameByte(byte[] b,AudioFormat af,boolean isSecond)
{
int ch=0;if(isSecond && af.getChannels()==2)ch=2;
int bytesize=af.getSampleSizeInBits()/8;
int framesize=af.getFrameSize();
int[] to=new int[b.length/framesize];
for(int i=0;i<to.length;i++)
{
to[i]=(int)b[i*framesize+ch];
if(bytesize==2)to[i]+=(int)b[i*framesize+ch+1]*256;
}
return to;
}
class SampleActionListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
try
{
if(e.getSource() == bt)
{
get();
}
else if(e.getSource() == bt2)
{
start();
}
else if(e.getSource() == bt3)
{
stop();
}
}
catch(Exception el)
{
}
}
}
class WavePanel extends JPanel
{
protected int[] dispData;
protected int[] widthData;
protected double amplitude=0.5;
public WavePanel()
{
super(true);
}
public void display(int data[])
{
dispData=data;
repaint();
}
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D)g;
g2.setBackground(Color.black);
g.setColor(Color.green);
g.clearRect(0, 0, this.getWidth(), this.getHeight());
if(dispData!=null && dispData.length>2)
{
int xx[]=new int[dispData.length];
int yy[]=new int[dispData.length];
int yyoffset=this.getHeight()/2;
double xdelta=(double)this.getWidth()/(double)dispData.length;
double ydelta=this.getHeight()/65536.0;
for(int i=0;i<dispData.length;i++)
{
xx[i]=(int)(xdelta*i);
yy[i]=(int)(ydelta*dispData[i]*amplitude)+yyoffset;
}
g.drawPolyline(xx, yy, dispData.length);
}
}
}
}