- ベストアンサー
javaで周波数や鳴る長さを設定できるプログラムを作りたいのですが
javaで周波数や鳴る長さを設定できるプログラムを作りたいのですが どんな方法で作れるのか分かりません。 ただのBeep音なら鳴らせるのですが周波数や長さを指定するにはどうしたらよいでしょう。 jBeepMakerというプログラムを見つけましたがplayボタンを押してもエラーが出て音がなりません。 javaでは無理なのでしょうか
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
どうも、#1です。 >せめてこのソースを理解できるようになるプログラミングの >良書など紹介していただけたらと思います Javaでピコピコシンセを作ってみよう! http://www.hakkaku.net/series/java%e3%81%a7%e3%83%94%e3%82%b3%e3%83%94%e3%82%b3%e3%82%b7%e3%83%b3%e3%82%bb%e3%82%92%e4%bd%9c%e3%81%a3%e3%81%a6%e3%81%bf%e3%82%88%e3%81%86%ef%bc%81 このサイトを参考にしました。 ここを読んでもらった方がわかりやすいと思います。 あと、ご質問についてですが、 >SquareWaveのパラメータの440Fってどうして16進数なんでしょう これは、16進数ではなく、float型の440ってことです。 ラの音が440Hzだそうなので、そうしました。 と言うことで、frequency は、音波の周波数です。 >振幅(長さ?)をbyteでキャストしてるのもわかりません ここは長さというより、波動の上下の振り幅です。 音波でいうと、音の大きさですね。 コンピューターでは、波動を、それぞれの瞬間の振幅値を格納したbyte配列として表すので、最初から引数をbyte型にしたので、キャストしています。 >サンプリングレートと周波数の違いが分かりません ここでいう周波数は音波の周波数です。この値が大きくなると、音程は高くなり、逆だと低くなります。 サンプリングレートは、どれくらい細かく音波をデータ化するかを表します。 具体的にいうと、今回は、44100という数値を使っていますが、これは、CDのサンプリングレートが、44.1kHzなので、こうしました。 つまり、1秒分の音の波を44100個のbyte配列で表しているわけです。 この値が多くなればなるほど、細かくサンプル化することでできるので、オリジナルの波の形に近づきます。 逆に少なければ、データサイズは小さくてすみますが、波の形は、オリジナルの形より、デコボコになります。 >SquareWaveクラスのコンストラクタの中で 1/frequency * sampleRate >としているのはなんのためだか・・・ これは、波の一周期分が何個のbyte配列で表せるかを計算しています。 具体的にすると、 (1 / 440Hz) * 44100Hz ラの音は1秒間に440回振動します。逆に言えば、1周期分にかかる時間は、1/440 秒です。 サンプリングレートは、44100です。つまり、一秒分の波を44100個のbyte配列で表します。 では、今回の一周期分の波に使われるbyte配列の数は、44100 * 1/440 で、100.227 つまり、ラの音は、一周期分の波を100個のbyte配列で表すことができる、となります。
その他の回答 (2)
- PecoPlus
- ベストアンサー率76% (144/188)
続きです。 矩形波データのクラスです。 public class SquareWave { //周波数 private float frequency; //振幅 private byte amplitude; //サンプリングレート private float sampleRate; private byte[] data; public SquareWave(float frequency, byte amplitude, float sampleRate) { this.frequency = frequency; this.amplitude = amplitude; this.sampleRate = sampleRate; int dataSize = (int)((1 / frequency) * sampleRate); data = new byte[dataSize]; makeWave(); } private void makeWave() { for (int i = 0; i < data.length; i++) { byte d = amplitude; if (i >= data.length / 2) d = (byte)(d * -1); data[i] = d; } } public AudioFormat getAudioFormat() { return new AudioFormat(sampleRate, 8, 1, true, true); } public InputStream getInputStream(int playTime) { return new WaveInputStream(playTime); } //データのアクセス用に InputStream を使うことにしました。 private class WaveInputStream extends InputStream { private long frameLength; private long framePos; private int index; private WaveInputStream(int playTime) { frameLength = (long)((sampleRate / 1000) * playTime); framePos = 0; index = 0; } @Override public int read() throws IOException { if (framePos >= frameLength) { return -1; } framePos++; if (index >= data.length) index = 0; int i = index; index++; return 0xFF & data[i]; } } }
お礼
「プーー」と鳴りました ありがとうございます でもまだわからないことだらけで・・・ 短形波ってなんでしょう。周波数が一定なら波形(サインカーブ?)を描くことが想像できません。 SquareWaveのパラメータの440Fってどうして16進数なんでしょう 振幅(長さ?)をbyteでキャストしてるのもわかりません サンプリングレートと周波数の違いが分かりません SquareWaveクラスのコンストラクタの中で 1/frequency * sampleRate としているのはなんのためだか・・・ せっかく貴重な時間を使ってサンプルを書いてもらったのにこんなに質問づくしでご迷惑だと思います・・・ せめてこのソースを理解できるようになるプログラミングの良書など紹介していただけたらと思います ありがとうございました
補足
あ、周波数って波形ですよね、FMとAMを思い出しました。 もうどこがわからないか分からなくなってきました。 とにかく実現できるということがわかっただけでも感謝です。 ありがとうございました。
- PecoPlus
- ベストアンサー率76% (144/188)
こんにちは。 私も音を鳴らすのは初めてなのですが、サウンドAPIを使うのだと思います。 ビープ音は矩形波だと聞いたので、ちょっとサンプルを作ってみました。 一応、音が鳴ったので、こんな感じでいいと思うのですが。 public class App { public static void main(String[] args) throws LineUnavailableException { SquareWave wave = new SquareWave(440F, (byte)10, 44100); SourceDataLine line = AudioSystem.getSourceDataLine(wave.getAudioFormat()); line.open(wave.getAudioFormat()); line.start(); InputStream in = wave.getInputStream(1000); byte[] b = new byte[1024]; int len = 0; try { while ((len = in.read(b)) > -1) { line.write(b, 0, len); } line.drain(); } catch (IOException ex) { ex.printStackTrace(); } line.close(); } }
お礼
PCMとかの知識が必要なんでしょうか ピコピコシンセというサイトをよく読んでみようと思います。 また質問することがあったらよろしくお願いします。 ありがとうございました