音量を自動で最大化する(2)

スポンサーリンク

前回最大化をするクラスを作りました。今回はこれを利用する側を作ります。こちらは以前に作ったファイル書き出し用のクラスWavFileWriterを修正していきます。

音量を自動で最大化する(1)

修正内容

コンストラクタ

今まではSoundReadableをそのまま内部で持っていましたがここではMaximizerに変更します。

public class WavFileWriter extends InputStream {

  public static final float SAMPLE_RATE = 48000;

  boolean signed = true;
  boolean big_endian = true;
  int sample_size_byte = 2;

  ArrayList list;

  Maximizer maximizer;

  public WavFileWriter(SoundReadable readable) throws IOException {
    list = new ArrayList<>();
    double volume = Math.pow(2, sample_size_byte * 8 - 1) - 1;
    maximizer = new Maximizer(readable, volume);
  }

既存メソッドの微修正

次にreadメソッドを直します。今まではSoundReadableから読み込んだ値に最大音量を係数としてかけていましたがMaximizer内部でこの処理は行うのでただ読み込んで返すだけになりました。

@Override
public int read() throws IOException {
  if (list.isEmpty()) {
    double value = maximizer.read();
    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;
}

同様に既存のSoundReadableから返す値もMaximizerで置き換えています。

public long length() {
  return maximizer.length();
}

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

一時ファイルを消すための処理を追加しました。

public void terminate() throws IOException {
  maximizer.terminate();
}

mainメソッドの修正

最後にmainメソッドを修正します。とはいっても最後に終了処理を呼び出すだけです。

FrequencyMap freqMap = new FrequencyMap(440.0);
freqMap.putFreq(2.0, 880.0);
WavFileWriter ss = new WavFileWriter(new OscillatorReader(new SineOscillator(), freqMap, 3));

AudioSystem.write(
  new AudioInputStream(ss, ss.getFormat(), ss.length()),
  AudioFileFormat.Type.WAVE, new File("/Users/minaberger/mywork/sine_440_880.wav"));
ss.terminate();

これで修正は終わりです。これからは音量に気にせず音を合成することができます。

ソース

以下ソースです。

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 WavFileWriter extends InputStream {

  public static final float SAMPLE_RATE = 48000;

  boolean signed = true;
  boolean big_endian = true;
  int sample_size_byte = 2;

  ArrayList list;

  Maximizer maximizer;

  public WavFileWriter(SoundReadable readable) throws IOException {
    list = new ArrayList<>();
    double volume = Math.pow(2, sample_size_byte * 8 - 1) - 1;
    maximizer = new Maximizer(readable, volume);
  }

  @Override
  public int read() throws IOException {
    if (list.isEmpty()) {
      double value = maximizer.read();
      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 maximizer.length();
  }

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

  public void terminate() throws IOException {
    maximizer.terminate();
  }

  public static void main(String[] arg) throws IOException {
    FrequencyMap freqMap = new FrequencyMap(440.0);
    freqMap.putFreq(2.0, 880.0);
    WavFileWriter ss = new WavFileWriter(new OscillatorReader(new SineOscillator(), freqMap, 3));

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

}
スポンサーリンク

シェアする

  • このエントリーをはてなブックマークに追加

フォローする

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