今まで作ったものを組み合わせてファイルの最大化ツールを作りました。
動作の検証
今回作ったツールの結果です。上が最大化後、下が最大化前です。

これで録音したファイルの音量が小さい場合には音量を最大にすることができるようになりました。
ソース
以下ソースです。
/*
* mocha-java.com *
*/
package mocha.sound;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.Map;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
/**
*
* @author minaberger
*/
public class WavFileMaximizer extends InputStream {
AudioFormat format;
BufferedInputStream bis;
double coef;
byte[] data;
int index;
boolean isBigEndian;
int sampleSize;
long frameLength;
public WavFileMaximizer(File wavFile) throws Exception {
AudioInputStream ais = AudioSystem.getAudioInputStream(wavFile);
format = ais.getFormat();
System.out.println("frame length : " + ais.getFrameLength());
System.out.println("sample rate : " + format.getSampleRate());
System.out.println("samble size : " + format.getSampleSizeInBits());
System.out.println("channels : " + format.getChannels());
System.out.println("big endian : " + format.isBigEndian());
System.out.println("mark supported : " + ais.markSupported());
Map properties = format.properties();
for (String key : properties.keySet()) {
System.out.println("property : " + key + "big endian = " + properties.get(key));
}
sampleSize = format.getSampleSizeInBits() / 8;
isBigEndian = format.isBigEndian();
frameLength = ais.getFrameLength();
data = new byte[sampleSize];
bis = new BufferedInputStream(ais);
int max = 0;
while (true) {
if (bis.read(data, 0, data.length) <= 0) {
break;
}
int value = toValue(data, isBigEndian);
max = Math.max(max, Math.abs(value));
}
bis.close();
System.out.println("max level(abs) : " + max);
coef = (double) (Math.pow(2, sampleSize * 8 - 1) - 1) / (double) max;
System.out.println("coefficient : " + coef);
bis = new BufferedInputStream(AudioSystem.getAudioInputStream(wavFile));
index = sampleSize;
}
public void maximize(File outFile) throws IOException {
AudioSystem.write(new AudioInputStream(this, format, frameLength), AudioFileFormat.Type.WAVE, outFile);
}
public static int toValue(byte[] data, boolean isBigEndian) {
int value = 0;
for (int i = 0; i < data.length; i++) {
int index = isBigEndian ? data.length - 1 - i : i;
if (i == data.length - 1) {
value += data[index] * Math.pow(2, i * 8);
} else {
value += Byte.toUnsignedInt(data[index]) * Math.pow(2, i * 8);
}
}
return value;
}
public static byte[] toData(int value, int sampleSize, boolean isBigEndian) {
ByteBuffer byteBuffer = ByteBuffer.allocate(4);
byteBuffer.putInt(value);
byte[] buffer = byteBuffer.array();
byte[] ret = new byte[sampleSize];
for (int i = 0; i < sampleSize; i++) {
int index = isBigEndian ? buffer.length - sampleSize + i : buffer.length - 1 - i;
ret[i] = buffer[index];
}
return ret;
}
@Override
public int read() throws IOException {
if (index >= data.length) {
if (bis.read(data, 0, data.length) <= 0) {
return -1;
}
int value = toValue(data, isBigEndian);
value *= coef;
data = toData(value, sampleSize, isBigEndian);
index = 0;
}
return Byte.toUnsignedInt(data[index++]);
}
public static void main(String[] args) throws Exception {
new WavFileMaximizer(new File("wav/origin.wav")).maximize(new File("wav/max.wav"));
}
}