Javaで矩形波のWavファイルを作成する(3)

スポンサーリンク

矩形波のwavファイルはこれまでなんども作ってますが少しずつ洗練したプログラムになって来ています。最適化といってこの先発展した処理をするにあたってここでの作業は無駄にはなりません。

Javaで矩形波のWavファイルを作成する(1)
Javaで矩形波のWavファイルを作成する(2)
Javaで矩形波のオシレーターを作る

各処理を見直す

クラス名とフィールド変数

汎用のwav्ファイル作成クラスとするために名前も汎用的なSampleWavという名前にしました。サンプルレートはどこからでも静的に参照できるようstaticにし変更できないようにfinalにしてあります。

また今までオシレータークラスを持つようにしていましたがここではOscillatableという前回作ったインターフェイスに変更しました。これでこのインタフェースを実装しているクラスであればこのクラスのオシレータとして利用できるようになります。他の処理はサイン波作成のときと同じです。

サインオシレーターを使ってサイン波の音声ファイルを作成する

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public class SampleWav extends InputStream {
public static final float SAMPLE_RATE = 48000;
boolean signed = true;
boolean big_endian = true;
int sample_size_byte = 2;
int channels = 1;
double freq;
double seconds;
ArrayList list;
double volume;
Oscillatable oscillatable;
long index = 0;
public class SampleWav extends InputStream { public static final float SAMPLE_RATE = 48000; boolean signed = true; boolean big_endian = true; int sample_size_byte = 2; int channels = 1; double freq; double seconds; ArrayList list; double volume; Oscillatable oscillatable; long index = 0;
public class SampleWav extends InputStream {
  public static final float SAMPLE_RATE = 48000;
  
  boolean signed = true;
  boolean big_endian = true;
  int sample_size_byte = 2;
  int channels = 1;
  double freq;
  double seconds;
  
  ArrayList list;
  double volume;
  
  Oscillatable oscillatable;
  long index = 0;

コンストラクタ

Oscillatableを引数に追加しました。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public SampleWav(Oscillatable oscillatable, double freq, double seconds){
this.freq = freq;
this.seconds = seconds;
list = new ArrayList<>();
volume = Math.pow(2, sample_size_byte * 8 - 1) - 1;
this.oscillatable = oscillatable;
}
public SampleWav(Oscillatable oscillatable, double freq, double seconds){ this.freq = freq; this.seconds = seconds; list = new ArrayList<>(); volume = Math.pow(2, sample_size_byte * 8 - 1) - 1; this.oscillatable = oscillatable; }
public SampleWav(Oscillatable oscillatable, double freq, double seconds){
  this.freq = freq;
  this.seconds = seconds;
  list = new ArrayList<>();
  volume = Math.pow(2, sample_size_byte * 8 - 1) - 1;
  this.oscillatable = oscillatable;
}

readメソッド他

他の処理はオシレーターのクラスからインタフェースの参照値oscillatableに変更された以外は同じです。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
@Override
public int read() throws IOException {
if(list.isEmpty()){
double value = oscillatable.read(freq, volume);
ByteBuffer buffer = ByteBuffer.allocate(8);
buffer.putLong((long) value);
byte[] array = buffer.array();
for (int i = 8 - sample_size_byte; i < 8; i++) {
list.add(array[i]);
}
}
int ret = Byte.toUnsignedInt(list.remove(0));
return ret;
}
public long length(){
return (long)(SAMPLE_RATE * channels * seconds);
}
public AudioFormat getFormat(){
return new AudioFormat(SAMPLE_RATE, sample_size_byte * 8, channels, signed, big_endian);
}
@Override public int read() throws IOException { if(list.isEmpty()){ double value = oscillatable.read(freq, volume); ByteBuffer buffer = ByteBuffer.allocate(8); buffer.putLong((long) value); byte[] array = buffer.array(); for (int i = 8 - sample_size_byte; i < 8; i++) { list.add(array[i]); } } int ret = Byte.toUnsignedInt(list.remove(0)); return ret; } public long length(){ return (long)(SAMPLE_RATE * channels * seconds); } public AudioFormat getFormat(){ return new AudioFormat(SAMPLE_RATE, sample_size_byte * 8, channels, signed, big_endian); }
@Override
public int read() throws IOException {
  if(list.isEmpty()){
    double value = oscillatable.read(freq, volume);
    ByteBuffer buffer = ByteBuffer.allocate(8);
    buffer.putLong((long) value);
    byte[] array = buffer.array();
    for (int i = 8 - sample_size_byte; i < 8; i++) {
      list.add(array[i]);
    }     
  }
  int ret = Byte.toUnsignedInt(list.remove(0));
  return ret;    
}
public long length(){
  return (long)(SAMPLE_RATE * channels * seconds);
}
public AudioFormat getFormat(){
  return new AudioFormat(SAMPLE_RATE, sample_size_byte * 8, channels, signed, big_endian);
}

メインの処理

メインの処理ではSampleWavを作成してオシレーターを作成して引数として指定しています。このSquareOscillatorを他のOscillatable実装クラスに変更すると音色を変えることができます。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public static void main(String[] arg) throws IOException {
SampleWav ss = new SampleWav(new SquareOscillator(SAMPLE_RATE), 440, 3);
AudioSystem.write(
new AudioInputStream(ss, ss.getFormat(), ss.length()),
AudioFileFormat.Type.WAVE, new File("/Users/myaccount/mywork/square_440.wav"));
}
public static void main(String[] arg) throws IOException { SampleWav ss = new SampleWav(new SquareOscillator(SAMPLE_RATE), 440, 3); AudioSystem.write( new AudioInputStream(ss, ss.getFormat(), ss.length()), AudioFileFormat.Type.WAVE, new File("/Users/myaccount/mywork/square_440.wav")); }
public static void main(String[] arg) throws IOException {
  SampleWav ss = new SampleWav(new SquareOscillator(SAMPLE_RATE), 440, 3);

  AudioSystem.write(
    new AudioInputStream(ss, ss.getFormat(), ss.length()),
    AudioFileFormat.Type.WAVE, new File("/Users/myaccount/mywork/square_440.wav"));
}

実行結果

音声ファイルは前回と全く同じものです。

音声プレーヤー

ソース

前回のものより洗練されてきました。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
package mocha.sound;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
public class SampleWav extends InputStream {
public static final float SAMPLE_RATE = 48000;
boolean signed = true;
boolean big_endian = true;
int sample_size_byte = 2;
int channels = 1;
double freq;
double seconds;
ArrayList list;
double volume;
Oscillatable oscillatable;
long index = 0;
public SampleWav(Oscillatable oscillatable, double freq, double seconds) {
this.freq = freq;
this.seconds = seconds;
list = new ArrayList<>();
volume = Math.pow(2, sample_size_byte * 8 - 1) - 1;
this.oscillatable = oscillatable;
}
@Override
public int read() throws IOException {
if (list.isEmpty()) {
double value = oscillatable.read(freq, volume);
ByteBuffer buffer = ByteBuffer.allocate(8);
buffer.putLong((long) value);
byte[] array = buffer.array();
for (int i = 8 - sample_size_byte; i < 8; i++) {
list.add(array[i]);
}
}
int ret = Byte.toUnsignedInt(list.remove(0));
return ret;
}
public long length() {
return (long) (SAMPLE_RATE * channels * seconds);
}
public AudioFormat getFormat() {
return new AudioFormat(SAMPLE_RATE, sample_size_byte * 8, channels, signed, big_endian);
}
public static void main(String[] arg) throws IOException {
SampleWav ss = new SampleWav(new SquareOscillator(SAMPLE_RATE), 440, 3);
AudioSystem.write(
new AudioInputStream(ss, ss.getFormat(), ss.length()),
AudioFileFormat.Type.WAVE, new File("/Users/myaccount/mywork/square_440.wav"));
}
}
package mocha.sound; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; import java.util.ArrayList; import javax.sound.sampled.AudioFileFormat; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; public class SampleWav extends InputStream { public static final float SAMPLE_RATE = 48000; boolean signed = true; boolean big_endian = true; int sample_size_byte = 2; int channels = 1; double freq; double seconds; ArrayList list; double volume; Oscillatable oscillatable; long index = 0; public SampleWav(Oscillatable oscillatable, double freq, double seconds) { this.freq = freq; this.seconds = seconds; list = new ArrayList<>(); volume = Math.pow(2, sample_size_byte * 8 - 1) - 1; this.oscillatable = oscillatable; } @Override public int read() throws IOException { if (list.isEmpty()) { double value = oscillatable.read(freq, volume); ByteBuffer buffer = ByteBuffer.allocate(8); buffer.putLong((long) value); byte[] array = buffer.array(); for (int i = 8 - sample_size_byte; i < 8; i++) { list.add(array[i]); } } int ret = Byte.toUnsignedInt(list.remove(0)); return ret; } public long length() { return (long) (SAMPLE_RATE * channels * seconds); } public AudioFormat getFormat() { return new AudioFormat(SAMPLE_RATE, sample_size_byte * 8, channels, signed, big_endian); } public static void main(String[] arg) throws IOException { SampleWav ss = new SampleWav(new SquareOscillator(SAMPLE_RATE), 440, 3); AudioSystem.write( new AudioInputStream(ss, ss.getFormat(), ss.length()), AudioFileFormat.Type.WAVE, new File("/Users/myaccount/mywork/square_440.wav")); } }
package mocha.sound;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;

public class SampleWav extends InputStream {

  public static final float SAMPLE_RATE = 48000;

  boolean signed = true;
  boolean big_endian = true;
  int sample_size_byte = 2;
  int channels = 1;
  double freq;
  double seconds;

  ArrayList list;
  double volume;

  Oscillatable oscillatable;
  long index = 0;

  public SampleWav(Oscillatable oscillatable, double freq, double seconds) {
    this.freq = freq;
    this.seconds = seconds;
    list = new ArrayList<>();
    volume = Math.pow(2, sample_size_byte * 8 - 1) - 1;
    this.oscillatable = oscillatable;
  }

  @Override
  public int read() throws IOException {
    if (list.isEmpty()) {
      double value = oscillatable.read(freq, volume);
      ByteBuffer buffer = ByteBuffer.allocate(8);
      buffer.putLong((long) value);
      byte[] array = buffer.array();
      for (int i = 8 - sample_size_byte; i < 8; i++) {
        list.add(array[i]);
      }
    }
    int ret = Byte.toUnsignedInt(list.remove(0));
    return ret;
  }

  public long length() {
    return (long) (SAMPLE_RATE * channels * seconds);
  }

  public AudioFormat getFormat() {
    return new AudioFormat(SAMPLE_RATE, sample_size_byte * 8, channels, signed, big_endian);
  }

  public static void main(String[] arg) throws IOException {
    SampleWav ss = new SampleWav(new SquareOscillator(SAMPLE_RATE), 440, 3);

    AudioSystem.write(
      new AudioInputStream(ss, ss.getFormat(), ss.length()),
      AudioFileFormat.Type.WAVE, new File("/Users/myaccount/mywork/square_440.wav"));
  }

}
スポンサーリンク

シェアする

フォローする

%d人のブロガーが「いいね」をつけました。