/*
Реализация спецификаций CLDC версии 1.1 (JSR-139), MIDP версии 2.1 (JSR-118)
и других спецификаций для функционирования компактных приложений на языке
Java (мидлетов) в среде программного обеспечения Малик Эмулятор.
Copyright © 2016, 2019 Малик Разработчик
Это свободная программа: вы можете перераспространять ее и/или изменять
ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
общественной лицензии GNU.
Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<https://www.gnu.org/licenses/>.
*/
package malik.emulator.fileformats.sound.sampled.wavelib;
import java.io.*;
import malik.emulator.fileformats.*;
import malik.emulator.fileformats.sound.*;
import malik.emulator.fileformats.sound.sampled.*;
public final class WaveEncoder extends Object
implements OutputAdapter, SoundEncoder, DataHolder, DataEncoder, SoundEncoderSampled
{
public static final int RIFF_SIGNATURE = 0x52494646;
private static final int DATA_SIGNATURE = 0x64617461;
private static final long WAVEFMT_SIGNATURE = 0x57415645666d7420L;
private static void writeShortLE(OutputStream stream, int src)
throws IOException
{
stream.write(src);
stream.write(src >> 8);
}
private static void writeIntLE(OutputStream stream, int src)
throws IOException
{
stream.write(src);
stream.write(src >> 8);
stream.write(src >> 16);
stream.write(src >> 24);
}
private int channels;
private int samplesPerSecond;
private short[] samples;
public WaveEncoder()
{
}
public void saveToOutputStream(OutputStream stream)
throws IOException, EmptyAdapterException
{
saveToDataStream(new DataOutputStream(stream));
}
public void saveToDataStream(DataOutputStream stream)
throws IOException, EmptyAdapterException
{
int i;
int j;
int len;
int sample;
int channels;
int samplesPerSecond;
byte[] data;
short[] samples;
if((samples = this.samples) == null)
{
throw new EmptyAdapterException("Кодирование Wave-файлов: " +
"адаптер пуст.");
}
data = new byte[(len = samples.length) << 1];
for(i = 0, j = 0; j < len; j++)
{
data[i++] = (byte) (sample = samples[j]);
data[i++] = (byte) (sample >> 8);
}
channels = this.channels;
samplesPerSecond = this.samplesPerSecond;
stream.writeInt(RIFF_SIGNATURE);
writeIntLE(stream, (len <<= 1) + 0x24);
stream.writeLong(WAVEFMT_SIGNATURE);
writeIntLE(stream, 0x10);
writeShortLE(stream, 0x01); /* алгоритм сжатия */
writeShortLE(stream, channels); /* количество каналов */
writeIntLE(stream, samplesPerSecond); /* частота дискретизации */
writeIntLE(stream, (samplesPerSecond * channels) << 1); /* количество байт в секунду */
writeShortLE(stream, channels << 1); /* выравнивание */
writeShortLE(stream, 0x10); /* разрядность отсчёта */
stream.writeInt(DATA_SIGNATURE);
writeIntLE(stream, len);
stream.write(data);
}
public void clear()
{
channels = 0;
samplesPerSecond = 0;
samples = null;
}
public boolean isEmpty()
{
return samples == null;
}
public void setSamples(int channels, int samplesPerSecond, short[] samples)
throws InvalidDataFormatException
{
if(channels != 1 && channels != 2)
{
throw new InvalidDataFormatException("Кодирование Wave-файлов: " +
"недопустимое количество каналов " + channels + ".");
}
if(samplesPerSecond <= 0 || samplesPerSecond > 0xffff)
{
throw new InvalidDataFormatException("Кодирование Wave-файлов: " +
"недопустимая частота дискретизации " + samplesPerSecond + ".");
}
if(samples == null)
{
throw new InvalidDataFormatException("Кодирование Wave-файлов: " +
"параметр samples равен нулевой ссылке.");
}
if(samples.length % channels != 0)
{
throw new InvalidDataFormatException("Кодирование Wave-файлов: " +
"параметр samples имеет недопустимую длину.");
}
this.channels = channels;
this.samplesPerSecond = samplesPerSecond;
this.samples = samples;
}
}