前提・実現したいこと
java sound apiを使用して波形を描画するプログラムを作っています。
java
1import java.awt.*; 2import java.awt.event.*; 3import java.util.*; 4 5import javax.sound.sampled.*; 6import javax.swing.*; 7class recordsys extends Observable{ 8 byte wavedata[]; 9 AudioFormat format; 10 DataLine.Info info; 11 TargetDataLine target; 12 AudioInputStream input; 13 boolean recmode; 14 double width=1;//録音時間(1秒) 15 int rate=44100;//サンプリングレート 16 public recordsys() { 17 try { 18 wavedata=new byte[(int)(width*rate)]; 19 format= new AudioFormat(rate,8,1,true,false); 20 info=new DataLine.Info(TargetDataLine.class, format); 21 target=(TargetDataLine)AudioSystem.getLine(info); 22 input= new AudioInputStream(target); 23 }catch(Exception e) { 24 System.out.println("ERROR"); 25 } 26 } 27 public void startrec() { 28 int i=0; 29 try{ 30 target.open(format); 31 target.start(); 32 while(i<5) { 33 input.read(wavedata,0,wavedata.length); 34 setChanged(); 35 notifyObservers(); 36 i++; 37 } 38 }catch(Exception e) { 39 System.out.println("ERROR"); 40 } 41 } 42 public void stoprec() { 43 target.stop(); 44 target.close(); 45 } 46 public byte[] getdata() { 47 return wavedata; 48 } 49 public int getdatalength() { 50 return wavedata.length; 51 } 52} 53class wavemake extends JPanel implements Observer{ 54 int x=800; 55 byte data[]; 56 int len; 57 recordsys sys; 58 public wavemake(recordsys r) { 59 sys=r; 60 len=sys.getdatalength(); 61 data=sys.getdata(); 62 r.addObserver(this); 63 } 64 public void paintComponent(Graphics g) { 65 super.paintComponent(g); 66 for(int i=0;i<x-1;i++) { 67 g.drawLine(i,-1*data[(int)(len*(double)i/x)]+127, 68 i+1,-1*data[(int)(len*(double)(i+1)/x)]+127); 69 } 70 } 71 public void update(Observable o,Object arg) { 72 data=sys.getdata(); 73 System.out.println("repaintします"); 74 repaint(); 75 try { 76 Thread.sleep(100); 77 } catch (InterruptedException e) { 78 e.printStackTrace(); 79 } 80 } 81} 82class controler extends JPanel implements ActionListener{ 83 JButton start,stop; 84 recordsys sys; 85 public controler(recordsys s) { 86 sys=s; 87 start= new JButton("開始"); stop=new JButton("停止"); 88 start.addActionListener(this); 89 stop.addActionListener(this); 90 this.setLayout(new GridLayout(1,2)); 91 this.add(start); 92 this.add(stop); 93 } 94 public void actionPerformed(ActionEvent ev) { 95 if(ev.getSource()==start) { 96 sys.startrec(); 97 }else if(ev.getSource()==stop) { 98 sys.stoprec(); 99 } 100 } 101} 102class soundwave extends JFrame{ 103 recordsys sys; 104 controler cont; 105 wavemake wave; 106 public static void main(String[] args) { 107 new soundwave(); 108 } 109 public soundwave() { 110 sys=new recordsys(); 111 cont=new controler(sys); 112 wave=new wavemake(sys); 113 this.setSize(800,400); 114 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 115 this.add(wave); 116 this.add(cont,BorderLayout.SOUTH); 117 this.setVisible(true); 118 } 119}
Jbuttonの「開始」ボタンを押すと5秒の間1秒毎に録音した音の波形が描画されるようにしたいと考えています。しかし波形が更新されず最後の1秒分しか描画されませんでした。updateメソッドは正常に実行されているようですが何故でしょうか。
追記
このプログラムは外部の音を録音してその波形を描画するというプログラムです。
repaintの問題は解決しましたが、別に謎のノイズが発生する問題が起きてしまいました。
机を叩いた時の波形です。最初の数秒間は正しい波形を描けているのですが、途中から、または停止させた時に机以外から音は出していないのに、
このような波形が出力されていまいました。
###改良版ソースコード
java
1import java.awt.*; 2import java.awt.event.*; 3import java.util.*; 4 5import javax.sound.sampled.*; 6import javax.swing.*; 7class recordsys extends Observable implements Runnable{ 8 byte wavedata[]; 9 AudioFormat format; 10 DataLine.Info info; 11 TargetDataLine target; 12 AudioInputStream input; 13 14 wavemake make; 15 boolean recmode; 16 double width=1;//録音時間(1秒) 17 //int rate=44100;//サンプリングレート 18 int rate=8000; 19 public recordsys() { 20 try { 21 wavedata=new byte[(int)(width*rate)]; 22 format= new AudioFormat(rate,8,1,true,false); 23 info=new DataLine.Info(TargetDataLine.class, format); 24 target=(TargetDataLine)AudioSystem.getLine(info); 25 input= new AudioInputStream(target); 26 }catch(Exception e) { 27 System.out.println("ERROR"); 28 } 29 recmode=true; 30 } 31 public void stoprec() { 32 recmode=false; 33 } 34 public void run() { 35 int i=0; 36 try{ 37 target.open(format); 38 target.start(); 39 recmode=true; 40 while(recmode&&i<10) { 41 input.read(wavedata,0,wavedata.length); 42 make.setdata(wavedata); 43 setChanged(); 44 notifyObservers(); 45 i++; 46 } 47 target.stop(); 48 target.close(); 49 }catch(Exception e) { 50 System.out.println("ERROR"); 51 } 52 } 53 public byte getdata(int i) { 54 if(i>=wavedata.length)return 0; 55 else return wavedata[i]; 56 } 57 public int getdatalength() { 58 return wavedata.length; 59 } 60 public void setwavemaker(wavemake m) { 61 make=m; 62 make.setdata(wavedata); 63 } 64} 65class wavemake extends JPanel implements Observer{ 66 int x=800; 67 int len; 68 byte data[]; 69 recordsys sys; 70 public wavemake(recordsys r) { 71 sys=r; 72 len=sys.getdatalength(); 73 74 r.addObserver(this); 75 } 76 public void paintComponent(Graphics g) { 77 super.paintComponent(g); 78 int val1,val2; 79 for(int i=0;i<len-1;i++) { 80 val1=Byte.toUnsignedInt(data[i]); 81 val2=Byte.toUnsignedInt(data[i+1]); 82 g.drawLine((int)(x*(double)i/len),val1,(int)(x*(double)(i+1)/len),val2); 83 } 84 } 85 public void update(Observable o,Object arg) { 86 repaint(); 87 } 88 public void setdata(byte d[]) {data=d;} 89} 90class controler extends JPanel implements ActionListener{ 91 JButton start,stop; 92 recordsys sys; 93 public controler(recordsys s) { 94 sys=s; 95 start= new JButton("開始"); stop=new JButton("停止"); 96 start.addActionListener(this); 97 stop.addActionListener(this); 98 this.setLayout(new GridLayout(1,2)); 99 this.add(start); 100 this.add(stop); 101 } 102 public void actionPerformed(ActionEvent ev) { 103 if(ev.getSource()==start) { 104 Thread thread=new Thread(sys); 105 thread.start(); 106 }else if(ev.getSource()==stop) { 107 sys.stoprec(); 108 } 109 } 110} 111class soundwave extends JFrame{ 112 recordsys sys; 113 controler cont; 114 wavemake wave; 115 public static void main(String[] args) { 116 new soundwave(); 117 } 118 public soundwave() { 119 sys=new recordsys(); 120 wave=new wavemake(sys); 121 sys.setwavemaker(wave); 122 cont=new controler(sys); 123 this.setSize(800,400); 124 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 125 this.add(wave); 126 this.add(cont,BorderLayout.SOUTH); 127 this.setVisible(true); 128 } 129}
回答4件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/03/09 07:05
2020/03/09 09:03 編集
2020/03/09 12:26
2020/03/09 12:51 編集
2020/03/09 14:17
2020/03/10 14:15
2020/03/10 16:42 編集
2020/03/17 15:11
2020/03/17 17:07 編集