前回最大化をするクラスを作りました。今回はこれを利用する側を作ります。こちらは以前に作ったファイル書き出し用のクラスWavFileWriterを修正していきます。
修正内容
コンストラクタ
今までは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(); } }