質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.80%

キーボードの、”n””m”を押すと音が鳴るサンプラーを作りたいのですが、 キーを押しても変化がありません。

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 176

キーボードの、”n””m”を押すと音が鳴るサンプラーを作りたいのですが、
AudioFormatのあたりで、例外が出ています。
例外:
javax.sound.sampled.LineUnavailableException: line with format PCM_SIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, little-endian not supported.
調べてみると、"LineUnavailableException は、ラインが使用不可のため開けないことを示す例外です。この状況がもっともよく発生するのは、要求されたラインがすでにほかのアプリケーションによって使用されている場合です。"と、ありました。
ちなみに、他のアプリケーションは、すべて閉じました。

       AudioFormat   frmt= new AudioFormat(44100,16,2,true,false);
       DataLine.Info info= new DataLine.Info(Clip.class,frmt);
       clip= (Clip)AudioSystem.getLine(info);
       clip.open(frmt,wave_data,0,wave_data.length);
       clip.start();


どなたか、ご指導くださる方、よろしくお願いいたします。

import java.awt.BorderLayout;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.KeyListener;
import java.awt.event.KeyEvent;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Dimension;

import java.lang.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.sound.sampled.*;

public class SynthAkira extends JFrame {

  public static void main(String[] args){

        SynthAkira akira = new SynthAkira("Synth Akira");
        akira.setVisible(true);
  }

  SynthAkira(String title){
    setTitle(title);
    setBounds(100, 100, 600, 600);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    Container contentPane = getContentPane();
    contentPane.add(new Main(), BorderLayout.CENTER);
    }
}

class Main extends JPanel {

  static byte[] wave_data = new byte[44100];

  static JSlider slider1 = new JSlider(0, 1000);
  static JSlider slider2 = new JSlider(0, 1000);
  JPanel p1;
  JPanel p2;
  JPanel p3;
    static JPanel p4;
  JPanel p5;
  JPanel p6, p7, p8;
  static JLabel label1;
  static JLabel label2;
  static JLabel label3;
  JButton button1, button2;

    Main() {

    slider1.setValue(100);
    slider1.setFocusable(false);
    slider1.addChangeListener(new Slider());
    slider2.setValue(100);
    slider2.setFocusable(false);
    slider2.addChangeListener(new Slider());

    p1 = new JPanel();
    p1.add(slider1);
    p1.add(slider2);

    label1 = new JLabel();
    label2 = new JLabel();
    label1.setText(""+slider1.getValue());
    label2.setText(""+slider2.getValue());

    p3 = new JPanel();
    p3.add(label1);
    p3.add(label2);

    p7 = new JPanel();
    p8 = new JPanel();
    Key key = new Key();
    p7.addKeyListener(key);
    p7.setFocusable(true);

    p2 = new JPanel();
    p2.setLayout(new BorderLayout());
    p2.add(p1, BorderLayout.NORTH);
    p2.add(p3, BorderLayout.CENTER);
    p2.add(p7, BorderLayout.SOUTH);

    label3 = new JLabel("");
    p4 = new JPanel();
    p4.setPreferredSize(new Dimension(600, 200));

    p4.setLayout(new BorderLayout());
    p4.add(label3, BorderLayout.NORTH);
    p4.add(new Paint(), BorderLayout.SOUTH);

    setLayout(new BorderLayout());
    add(p2, BorderLayout.NORTH);
    add(p4, BorderLayout.CENTER);
//    p5.PpsetPreferredSize(new Dimension(600, 350));
  }
}
class Key implements KeyListener {

   int i;

   public void keyPressed(KeyEvent e) {
    Main.label3.setText(e.getKeyText(e.getKeyCode()));
    if(e.getKeyCode() == KeyEvent.VK_N) {
      new Sound(1);
    }else if(e.getKeyCode() == KeyEvent.VK_M) {
      new Sound(2);
    }
    Main.p4.add(new Paint());
    }

  public void keyReleased(KeyEvent e) {
//    clip.drain();
//    clip.close();
//    clip.stop();
  }
  public void keyTyped(KeyEvent e) {}
}

class Paint extends JPanel {

  protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    g.setColor(Color.RED);
    for(int i = 0; i < (Main.wave_data.length/200-1); i++) {
          g.drawLine(i*2,128-Main.wave_data[i*200],(i+1)*2,128-Main.wave_data[(i+1)*200]);
    }
  }
}

class Sound {

  Clip clip;

  Sound(int i) {
      double l1 = i*Main.slider1.getValue()/44100.0;
      double l2 = i*Main.slider2.getValue()/44100.0;
      for(int j=0;j<Main.wave_data.length;j++){
          Main.wave_data[j]= (byte)(110*(Main.wave_data.length-(j+1))/Main.wave_data.length*Math.sin((j*l1)*Math.PI*2)
          *Math.sin((j*l2)*Math.PI*2));
        }

    try{
       AudioFormat   frmt= new AudioFormat(44100,16,2,true,false);
       DataLine.Info info= new DataLine.Info(Clip.class,frmt);
       clip= (Clip)AudioSystem.getLine(info);
       clip.open(frmt,Main.wave_data,0,Main.wave_data.length);
       clip.start();
     }
    catch(Exception e){e.printStackTrace(System.err);}
    }
}

class Slider implements ChangeListener {
  public void stateChanged(ChangeEvent e) {
    Main.label1.setText(""+Main.slider1.getValue());
    Main.label2.setText(""+Main.slider2.getValue());
}
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • TN8001

    2020/10/18 22:54

    いろいろ試行錯誤されているのはわかりますが、変更点が明後日の方向です。

    >line with format PCM_SIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, little-endian not supported.
    とエラーがなっているんですから、つまり
    >new AudioFormat(44100,16,2,true,false);
    ここの部分ですよね?
    そこ以外をいくら変えても問題は解決しないでしょう。

    まずは前回の質問で動いていた(?)
    >new AudioFormat(44100,8,1,true,false);
    ならどうなりますか?

    キャンセル

  • akirasada1972

    2020/10/18 23:09

    すみません。
    前回は、Linuxを利用し、今回はWindows10でやっています。
    Linuxでは、どちらも動きました。

    キャンセル

  • TN8001

    2020/10/18 23:31

    Windows10ではどちらも動かないという意味ですか?
    私は音声データについてよくわからないので、残念ながら適切なアドバイスができません。

    すくなくともタイトルの件は解決されていると思うので、この質問はクローズし新たに質問を立てていただきたいです。

    その際は音声再生だけに絞ったコードで、やりたい事・参考サイト・開発環境等を明確にしてください(このコードのまま質問されると「過去に投稿した質問と同じ内容の質問」とマイナス評価される可能性があります)

    キャンセル

回答 1

checkベストアンサー

0

KeyListenerがどのコンポーネントにも登録されていないように見えます。
JPanel#addKeyListenerでlistenerを登録する必要があります。

例えば、こんな風に
p1 = new JPanel();
p1.addKeyListener(this);

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/10/16 00:09

    `JPanel`はデフォルトだとキーボードフォーカスを取らないため、`setFocusable(true)`も必要です^^

    キャンセル

  • 2020/10/16 12:26

    そうなんですね。訂正ありがとうございます。

    キャンセル

  • 2020/10/17 23:23

    修正をしたところ、キーボードからの信号を受け取ることは、できるようになったのですが、スライダーを動かすと、信号が受け取れなくなります。

    キャンセル

  • 2020/10/18 06:13

    キーボードフォーカスがスライダーに行っています。
    Tabキーを1,2回押せばパネルに戻ります。
    面倒なら
    slider1.setFocusable(false);
    としてフォーカスを取らないようにしてもいいです。

    この使い方だと InputMap ActionMap でやったほうがいいかもしれません。
    [How to Use Key Bindings (The Java™ Tutorials > Creating a GUI With JFC/Swing > Using Other Swing Features)](https://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.html


    エラーの件は再現しないので何とも言えませんが、キーを押している間 keyPressed が連続で来ます(キーリピート)その兼ね合いかもしれません。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.80%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • トップ
  • Javaに関する質問
  • キーボードの、”n””m”を押すと音が鳴るサンプラーを作りたいのですが、 キーを押しても変化がありません。