Общие сведения |
Предыдущая Содержание Следующая |
![]() |
При синтезе результатом работы является поток звуковых данных, которые далее можно либо проиграть, либо записать как звуковой файл.
PCM wav файл имеет простую структуру, состоящую из заголовка и данных. ЗаголовокЗаголовок содержит информацию, позволяющую определить, как надо работать с данными.
wav_header = {'R', 'I', 'F', 'F',//sRIFF [4] 0, 0, 0, 0,//riff_size//full_size - 8 'W', 'A', 'V', 'E', 'f', 'm', 't', ' ',//sWAVEfmt[8] 0x10, 00, 00, 00,//nExt 0x01, 00,//wFormatTag 0x01, 00,//nChannels 0x11, 0x2B, 00, 00,//nSamplesPerSec 0x11, 0x2B, 00, 00,//nAvgBytesPerSec 0x01, 00,//nBlockAlign 0x08, 00,//wBitsPerSample 'd', 'a', 't', 'a',//sdata[4] 00, 00, 00, 00};//data_size//full_size - 44
Поля заголовка. Для всех полей младший байт - первый: sRIFF - текстовое поле "RIFF". 4 байта. RIFF size - 4 байта, определяющие размер идущих дальше данных. RIFF size = полное число данных в байтах (включая заголовок) - 8. sWAVEfmt - текстовое поле "WAVEfmt ", 8 байт. nExt - дополнительное поле. 4 байта. Для PCM файла 0x00000010. wFormatTag - поле, определяющее алгоритм компрессии. 2 байта. Для PCM файла 0x00000001. nChannels - число каналов. 2 байта. nSamplesPerSec - число сэмплов в секунду. 4 байта. nSamplesPerSec = частота дискретизации. nAvgBytesPerSec - число байтов в секунду. 4 байта. nAvgBytesPerSec = частота дискретизации * число каналов * ( число бит в сэмпле / 8 ). nBlockAlign - число байтов на блок данных. 2 байта. nBlockAlign = число бит в сэмпле / 8 * число каналов. wBitsPerSample - число битов в сэмпле. 2 байта. sdata - текстовое поле "data". 4 байта. data size - размер данных. data size = полное число данных в байтах (включая заголовок) - 44. ЗвукЗвуковые данные располагаются после заголовка и представляют собой просто числовые значения отсчетов. Для 8-ми битных данных средним уровнем считается число 128. Таким образом, числу 0 соответствует -128 (минимальное значение), числу 255 соответствует 127 (максимальное значение). Для 16-ти битных данных средним уровнем считается число 0. Таким образом, -32768 - минимальное значение, 32767 - максимальное.
Пример, стерео, 16 бит: л1, п1, л2, п2, л3, п3... Реализацияpublic final class Snd { private static int m_sampleRate = 32000; // //private static final int RIFF = 0; private static final int RIFF_SIZE = 4; //private static final int WAVE_FMT = 8; //private static final int EXT = 16; //private static final int FORMAT_TAG = 20; private static final int CHANNELS = 22; private static final int SAMPLES_PER_SEC = 24; private static final int AVG_BYTES_PER_SEC = 28; private static final int BLOCK_ALIGN = 32; private static final int BITS_PER_SAMPLE = 34; //private static final int SDATA = 36; private static final int DATA_SIZE = 40; private static byte[] wav_header = {'R', 'I', 'F', 'F',//sRIFF [4] 0, 0, 0, 0,//riff_size//full_size - 8 'W', 'A', 'V', 'E', 'f', 'm', 't', ' ',//sWAVEfmt[8] 0x10, 00, 00, 00,//nExt 0x01, 00,//wFormatTag 0x01, 00,//nChannels 0x11, 0x2B, 00, 00,//nSamplesPerSec 0x11, 0x2B, 00, 00,//nAvgBytesPerSec 0x01, 00,//nBlockAlign 0x08, 00,//wBitsPerSample 'd', 'a', 't', 'a',//sdata[4] 00, 00, 00, 00};//data_size//full_size - 44 // public static void setSoundFormat(int sampleRate, int bitPerSample, int channels) { m_sampleRate = sampleRate; valueToByte( sampleRate, 4, wav_header, SAMPLES_PER_SEC ); valueToByte( sampleRate * channels * ( bitPerSample / 8 ), 4, wav_header, AVG_BYTES_PER_SEC ); valueToByte( bitPerSample, 2, wav_header, BITS_PER_SAMPLE ); valueToByte( bitPerSample * channels / 8, 2, wav_header, BLOCK_ALIGN ); valueToByte( channels, 2, wav_header, CHANNELS ); } public static int getSampleRate() { return m_sampleRate; } public static void valueToByte(long value, int byteCount, byte[] data, int offset) { for(int i = 0; i < byteCount; i++) data[offset++] = (byte) (value >> (i << 3)); } public static void writeHeader(byte[] snd) { System.arraycopy( wav_header, 0, snd, 0, wav_header.length ); Snd.valueToByte( snd.length - 8, 4, snd, RIFF_SIZE ); Snd.valueToByte( snd.length - wav_header.length, 4, snd, DATA_SIZE ); } public static byte[] toSndStream(short[] d) { byte[] b = new byte[d.length * 2 + wav_header.length]; for( int i = wav_header.length, k = 0; i < b.length; ) { int s = (int)d[k++]; b[i++] = (byte)s; b[i++] = (byte)(s>>8); } Snd.writeHeader( b ); return b; } public static byte[] toSndStream(double[] d) { byte[] b = new byte[d.length * 2 + wav_header.length]; for( int i = wav_header.length, k = 0; i < b.length; ) { int s = (int)d[k++]; b[i++] = (byte)s; b[i++] = (byte)(s>>8); } Snd.writeHeader( b ); return b; } }
|
Предыдущая Содержание Следующая |