MPEG-кодування стереозвуку

Слух людини використовує різноманітні алюзії для визначення розташування джерела звуку Найбільш очевидним критерієм є рівень гучності: якщо звук сильніше чується лівим вухом, то, швидше за все, його джерело також знаходиться зліва від слухача Однак існують і інші, менш помітні, нюанси Наприклад, звук, видаваний зліва від вас, досягне лівого вуха трохи раніше, ніж правого Крім того, вушна раковина влаштована так, щоб злегка змінювати звуки залежно від розташування джерела звуку Внутрішнє вухо і мозок володіють здатністю помічати ці незначні зміни, що в результаті дає вельми точну інформацію про розташування джерела звуку

Єдиний спосіб, що дозволяє зберегти всі ці алюзії, полягає в тому, щоб записати і стиснути сигнали правого і лівого каналів окремо Однак вухо людини неоднаково чутливо до всіх цих потенційно важливих деталей Ha високих частотах, зокрема, відносний рівень звуку більш значущий, ніж які-небудь інші характеристики B стандарті MPEG ці варіації чутливості використані для підвищення якості компресії стереосігналов

B звичайному режимі запису стереозвуку формат MPEG припускає зберігання двох незалежних комплектів вибірок, по одному для кожного каналу Очевидно, що такий варіант дозволяє зберегти всі необхідні деталі Альтернативним є методстереоінтенсівності,відповідно до якого зберігається тільки один набір відліків і різнімасштабні коефіцієнти(Рівні) для кожного каналу При використанні цього методу без змін зберігається лише ставлення рівнів між правим і лівим каналами

B більшості випадків для запису стереозвуку в MPEG файлах застосовується метод обєднаного стерео B відповідності з ним запис низькочастотних піддіапазонів проводиться так само, як і проста запис стереозвуку (тобто для кожного з каналів записуються свої відліки), в той час як для запису високочастотних піддіапазонів використовується інтенсивність стерео (розрізняються тільки масштабні коефіцієнти)

B MPEG Layer 3 доданий ще режимMS-cmepeo  -Проміжний варіант між вищеописаними методами По суті, при використанні цього методу окремі лівий і правий канали перетворяться в середній канал (тобто в суму вихідних) і бічний (Їх різницю) При декодуванні для отримання значень лівого каналу до середнього каналу додається бічній, а для отримання значень правого каналу бічній віднімається Перевага даної схеми полягає в тому, що для запису бокового каналу не потрібно великої точності

При кодуванні MPEG Layer I в кожному фреймі записується 12 груп з

32 відліків піддіапазонів Для запису кожного відліку потрібно від 2 до 15 біт

Щоб витягти біти, необхідно спочатку визначити, скільки бітів потрібно брати при читанні кожного відлікурозподілбітів), а також, наскільки потрібно посилити отримувані внаслідок відліки (масштабні коефіцієнти)

Перший рівень передбачає зберігання розподілу і коефіцієнтів посилення в абсолютній формі Значення розподілу записуються у вигляді послідовностей 4-бітових величин, а масштабні коефіцієнти у вигляді послідовностей 6-бітових величин

Лістинг 1419 Декодування фрейма Layer 1

void DecompressMpeg::LayerlDecode() {

int allocation [2] [32] / / Один для кожного каналу

/ / І піддіапазону

ResetBits()

int scaleFactor [2] [32] / / Один для кожного каналу

/ / І піддіапазону

long sbSamples [2] [32] / / Відліки

for (int gr = 0 gr <12; gr + +) {/ / Читаємо 12 груп відліків. if (_channels == 1) {

} Else {/ / Стерео

}

}

}

Зберігання розподілу в Layer 1

4-бітові значення розподілу показують, скільки бітів в даному піддіапазоні використовується для зберігання кожного відліку Якщо яке-небудь з розподілів одно 0, для цього піддіапазону НЕ будуть зберігатися ні відліки, ні масштабні коефіцієнти Це дозволяє при кодуванні виключати з фрейма деякі піддіапазони Завдяки тому що піддіапазони, записані в режимі стереоінтенсівності, використовують один відлік для запису обох каналів, необхідно зберігати тільки одне значення розподілу, а не по одному для кожного каналу

Щоб у потоці бітів не з `являлися помилкові синхрогрупи, розподіл ніколи не буває виражено числом, репрезентованою послідовністю одних одиниць

Лістинг 1420 Читання значень розподілу Layer 1

if(_channels == 1) {

/ / Для монозаписи зберігається одне значення розподілу

/ / Для кожного

/ / Піддіапазону

for(int sb=0sb&lt32sb++)

allocation[0][sb] = GetBits(4)

} Else {/ / Стереозапис злегка складніше

/ / Отримуємо незалежні розподілу для діапазону

/ / З повною записом стерео int sb

for(sb=0sb&lt_boundsb++) { allocation[0][sb] = GetBits(4) allocation[1][sb] = GetBits(4)

}

/ / Отримуємо обєднане розподіл для діапазонів

/ / Інтенсивності стерео

for(sb&lt32sb++) { allocation[0][sb] = GetBits(4) allocation[1][sb] = allocation[0][sb]

}

}

Масштабні коефіцієнти в Layer 1

B окремому фреймі міститься 12 наборів з 32 відліків піддіапазонів Домагаючись більшої економії місця, компресор може балансувати двома параметрами Величина розподілу визначає, скільки значень може бути збережено в заданому піддіапазоні Якщо в ході запису 12 наборів значень великого зміни характеру коливань не спостерігається, має сенс використовувати для його зберігання менше бітів Для контролю за загальною амплітудою діапазону застосовується масштабний коефіцієнт, який являє собою індекс в таблиці значень

Лістинг 1421 Читання масштабних коефіцієнтів Layer 1

{

for(int sb=0 sb&lt32 sb++)

for(int ch=0 ch&lt_channels ch++)

if(allocation[ch][sb] = 0) {

scaleFactor[ch][sb] = GetBits(6)

}

}

Зберігання відліків в Layer 1

Після отримання величини розподілу та масштабного коефіцієнта,

складнощів з читанням відліків піддіапазону не виникне Величина розподілу

показує, скільки бітів відведено на один відлік Нульове розподіл свідчить про те, що жодного біта відліку не записане Розподіл, величина якого лежить в діапазоні від 1 до 14, показує, що для запису одного значення відводиться від 2 до 15 біт Розподіл не може приймати значення 15, оскільки в іншому випадку не виключена поява помилкових синхрогрупи

Кожен відлік необхідно реконструювати в повноцінне 16-бітове число, після чого помножити на масштабний коефіцієнт (Фактично в стандарті ISO всі обчислення виробляються за правилами арифметики з плаваючою точкою)

Після того як буде підготовлена ​​група з 32 відліків піддіапазону, необ-

хідно провести синтез піддіапазону і відтворити 32 відліку ІКМ

Лістинг 1422 Читання і декодування відліків піддіапазонів монозаписи Layer 1

for (int sb = 0 sb <32; sb + +) / / Прочитуємо групу з 32 відліків. if (! allocation [0] [sb]) / / Відсутні біти?

sbSamples[0][sb] = 0

else {

int width = allocation[0][sb]+1

long s = GetBits(width)

/ / Передискретизация

/ / І масштабування цього відліку sbSamples [0] [sb] = Layer1Requant (s, width,

scaleFactor[0][sb])

} Layerl2Synthesis(_V[0],sbSamples[0],32,_pcmSamples[0])

_pcmSamples[0] += 32

_samplesRemaining += 32

При роботі зі стереозаписью діє та ж ідея, але вона ускладнюється необхідністю одночасної обробки піддіапазонів, записаних як повне стерео, і піддіапазонів інтенсивності стерео При обробці останніх обидва канали повинні масштабироваться незалежно один від одного, навіть якщо вони спільно використовують єдине значення

Лістинг 1423 Читання і декодування відліків піддіапазонів стереозаписи Layer 1

{/ / Отримуємо відліки для піддіапазонів з повною записом стерео for (int sb = 0 sb <_bound; sb + +)

for(int ch=0ch&lt2ch++)

if(allocation[ch][sb])

sbSamples[ch][sb] = 0

else {

int width = allocation[ch][sb]+l

long s = GetBits(width)

/ / Передискретизация і масштабування

/ / Отриманих значень

sbSamples[ch][sb] = Layer1Requant(s, width, scaleFactor[ch][sb])

}

}

{/ / Отримуємо загальні відліки для піддіапазонів,

/ / Використовують інтенсивність стерео for (int sb = 0 sb <_bound; sb + +) {

if( allocation[0] [sb])

sbSamples[0][sb] = 0

else {

int width = allocation[0][sb]+l

long s = GetBits(width)

/ / Передискретизация і масштабування відліку

/ / Для кожного каналу

sbSamples[0][sb] = LayerlRequant(s, width, scaleFactor[0][sb])

sbSamples[1][sb] = LayerlRequant(s, width, scaleFactor[1][sb])

/ / A тепер реконструюємо кожен з каналів

for(int ch=0ch&lt_channelsch++) { Layer12Synthesis(_V[ch],sbSamples[ch],32,_pcmSamples[ch])

_pcmSamples[ch] += 32

}

_samplesRemaining += 32

}

}

}

Передискретизація і масштабування в Layer 1

Передискретизацієюназивається процес перетворення коротких (що займають від 2 до 15 біт) відліків в значення одного виду Наведена нижче програма перетворить відліки до 16-бітним значенням зі знаком

Операція передискретизації відображає всілякі n-бітові коди відліків в набір розташованих на рівних відстанях один від одного чисел, що лежать в діапазоні від -1 до +1 Наприклад, у трьох бітах може бути записано 7 кодів (коди, повністю складені з одиниць, використовувати не можна, щоб не викликати появу неправдивої синхрогрупи) Коди від 0 до 6 відображені, відповідно, на -6 / 7, -4 / 7, -2 / 7, 0, 2/7, 4/7 і 6/7

Лістинг 1424 Функція передискретизації Layer 1

static long *layerlScaleFactors = 0

/ / Беззнакове число з фіксованою

/ / Точкою формату 115

/ / Повертаємо значення у форматі 216,

/ / Отримане після передискретизації

/ / І масштабування

inline long LayerlRequant(long sample, int width, int scaleIndex)

{

long levels = (1&lt&ltwidth)-1

return (layerlScaleFactors[scaleIndex] * (((sample+sample+1 levels)&lt&lt15)/levels)

)&gt&gt14

}

Значення масштабних коефіцієнтів відповідають експоненційної функції

Лістинг 1413 Ініціалізація загальних змінних Layer 1 і Layer2 (продовження)

if(layerlScaleFactors) { layerlScaleFactors = new long[63] for(int i = 0 i&lt63i++) {

layerlScaleFactors[i] = static_cast&ltlong&gt

(327670 * pow(20, 10 i/30))

}

}

Лістинг 1414 Очищення ресурсів MPEG (продовження)

delete layerlScaleFactors

layerlScaleFactors = 0

Концептуально MPEG Layer 2 нічим не відрізняється від MPEG Layer 1 Проте формат Layer 2 дозволяє скористатися додатковими можливостями, щоб зменшити в результаті число бітів:

 ‰ Ð ² Â Ñ Ð ¾ Ñ € Ð ¼ Ð ° Ñ, Ðμ  Layer  2  Р· Ð ° ÐÐμÐ ¹ Ñ Ñ, Ð ² Ð ¾ Ð ² Ð ° Ð ½ Ð ¾  Р¼ ÐμÐ ½ ÑŒÑÐμ  Р¿Ð ¾ ÐÐÐ ¸ Ð ° Ð ¿Ð ° Ð · Ð ¾ Ð ½ Ð ¾ Ð ² Â Ñ Â Ð ¼ Ð ° Ð »Ñ <Ð ¼ Ð ¸ Â Ñ Ð º Ð ¾ Ñ € Ð ¾ Ñ Ñ, Ñ Ð ¼ Ð ¸   Р¿ÐμÑ € ÐμÐ'Ð ° Ñ ‡ Ð ¸   Р± Ð ¸ Ñ, Ð ¾ Ð ².   ÐÑ, Ð ¾   Р¿Ð ¾ Ð · Ð ² Ð ¾ Ð »Ñ ÐμÑ, Â Â Ñ Ð ½ Ð ¸ Ð · Ð ¸ Ñ, ь  Р¾ Ð ± ÑŠÐμÐ ¼   Ñ, Ñ € ÐμÐ ± уÐμÐ ¼ Ð ¾ Ð ¹   Р¸ Ð ½ Ñ" Ð ¾ Ñ € Ð ¼ Ð ° Ñ † Ð ¸ Ð ¸ Ð ¾ Ñ ​​€ Ð ° Ñ Ð ¿Ñ € ÐμÐ'ÐμÐ »ÐμÐ ½ Ð ¸ Ð ¸;

 ‰ Ð ²  Р¾ Ñ, ÐÐμÐ »ÑŒÐ ½ Ð ¾ Ð ¼ Â Ñ Ñ € ÐμÐ ¹ Ð ¼ Ðμ  Layer  2 Â Ñ .. Ñ € Ð ° Ð ½ Ñ Ñ, Ñ Ñ Â Ñ, Ñ € Ð ¸  Р³ Ñ € уР¿Ð ¿Ñ < Р¿Ð ¾  12  Р¾ Ñ, Ñ Ñ ‡ ÐμÑ, Ð ¾ Ð ²  Р¸ Â Ñ € Ð ° Ð · Ñ € Ðμ-

шается використовувати загальні коефіцієнти масштабування для трьох груп значень (в Layer 1 міститься тільки одна група з 12 відліків)

 ‰ Ð ² Ð ¼ ÐμÑ Ñ, Ð ¾   Р½ ÐμÐ · Ð ° Ð ² Ð ¸ Ñ Ð ¸ Ð ¼ Ð ¾ Ð ³ Ð ¾ Â Â Ñ .. Ñ € Ð ° Ð ½ ÐμÐ ½ Ð ¸ Ñ Â Â ÐÐ ² Ð ¾ Ð ¸ Ñ ‡ Ð ½ Ð ¾ Ð ³ Ð ¾   Рº Ð ¾ ÐÐ °   ÐÐ »Ñ   Рº Ð ° Ð ¶ ÐÐ ¾ Ð ³ Ð ¾   Р¸ Ð ·   Р¾ Ñ, Ñ Ñ ‡ ÐμÑ, Ð ¾ Ð ²

піддіапазонів частина відліків може бути згрупована в єдиний дво-

ічний код

Структура декодера Layer 2 не схожа на структуру декодера Layer 1 Основна відмінність полягає в тому, що обробляється 36 наборів відліків піддіапазонів Ці набори діляться на 3 групи (по 12 штук в кожній), в яких можуть бути

різні масштабні коефіцієнти Кожна група з 12 значень поділена на 4 групи по 3 елементи Ha рис 141 показано, як набори відліків піддіапазонів збираються в групи по 3 (з метою комбінування східних відліків) і по 12 (це дозволяє їм спільно використовувати один набір масштабних коефіцієнтів)

Лістинг 1425 Layer 2: декодування фрейма

void DecompressMpeg::Layer2Decode() {

int allocation [2] [32] / / По одному для кожного каналу

/ / І піддіапазону

ResetBits()

int scaleFactor [3] [2] [32] / / По одному для кожного каналу

/ / І піддіапазону

long sbSamples [3] [2] [32] / / Три набору відліків

/ / Піддіапазонів

for (int sf = 0 sf <3; sf + +) {/ / Різні масштабні

/ / Коефіцієнти для

/ / Кожної третини

for (int gr = 0 gr <4; gr + +) {/ / 4 групи відліків

/ / В кожній третини

}

}

}

Зберігання розподілу в Layer 2

Для зберігання коливань в низькочастотних піддіапазонах потрібна більша дозвіл, ніж при запису високочастотних піддіапазонів звуку Тому в стандарті Layer 2 забезпечуються тісніші рамки розподілу памяті для високочастотних піддіапазонів Грунтуючись на інформації про швидкість передачі бітів і частоті дискретизації звуку, алгоритми Layer 2 визначають конкретну стратегію зберігання інформації про розподіл памяті

Наприклад, при швидкості передачі 32 000 біт в секунду і частоті дискретизації 32000 відліків в секунду алгоритми Layer 2 використовують таблиці LayerAllocationB2d Вони були взяті з таблиці під назвою B2d, наведеною в специфікаціях ISO докладніше ми поговоримо про них трохи пізніше B відповідності з певною стратегією 4 біти використовуються з метою вказівки розподілу для кожного з розташованих нижче двох піддіапазонів, 3 біта для кожного з наступних десяти, а 20 старших піддіапазонів не зберігається взагалі Таким чином, для опису інформації про розподіл памяті у файлі з монозапісью знадобилося б усього 38 біт проти 128, які були б потрібні, якби файл ставився до формату Layer 1

Крім того, значення, що зберігається в якості величини розподілу, що не число бітів, що витрачається для зберігання кожного відліку Ha насправді це посилання на клітинку в таблиці Вміст комірок згаданої таблиці це покажчики накласи квантування,про які я розповім нижче Важливо відзначити, що, засновуючи вибір стратегії розподілу памяті на швидкості передачі бітів і використовуючи посилання на таблиці замість прямих значень, компресор Layer 2 володіє великими можливостями для точної коригування потреб у памяті

Лістинг 1426 Layer2: таблиці розподілу бітів

Layer2QuantClass *l2allocationA[] = {0,&ampl2qc3,&ampl2qc7,&ampl2qc15,

&ampl2qc31,&ampl2qc63,&ampl2qcl27,&ampl2qc255,&ampl2qc511,&ampl2qcl023,&ampl2qc2047,

&ampl2qc4095,&ampl2qc8191,&ampl2qc16383,&ampl2qc32767,&ampl2qc65535} Layer2QuantClass *12allocationB[] =

{0,&ampl2qc3,&ampl2qc5,&ampl2qc7,&ampl2qc9,

&ampl2qc15,&ampl2qc31,&ampl2qc63,&ampl2qc127,&ampl2qc255,&ampl2qc511,&ampl2qcl023,&ampl2qc2047,

&ampl2qc4095,&ampl2qc8191,&ampl2qc65535}

Layer2QuantClass *12allocationC[] = {0,&ampl2qc3,&ampl2qc5,&ampl2qc7,

&ampl2qc9,&ampl2qc15,&ampl2qc31,&ampl2qc65535}

Layer2QuantClass *l2allocationD[] = {0,&ampl2qc3,&ampl2qc5,&ampl2qc65535} Layer2QuantClass *l2allocationE[] = {0,&ampl2qc3,&ampl2qc5,&ampl2qc9,

&ampl2qc15,&ampl2qc31,&ampl2qc63,&ampl2qc127,&ampl2qc255,&ampl2qc511,&ampl2qc1023,&ampl2qc2047,

&ampl2qc4095,&ampl2qc8191,&ampl2qc16383,&ampl2qc32767} Layer2QuantClass *l2allocationF[] =

{0,&ampl2qc3,&ampl2qc5,&ampl2qc7,&ampl2qc9,

&ampl2qc15,&ampl2qc31,&ampl2qc63,&ampl2qc127,&ampl2qc255,&ampl2qc511,&ampl2qc1023,&ampl2qc2047,

&ampl2qc4095,&ampl2qc8191,&ampl2qc16383}

struct Layer2BitAllocationTableEntry {

char _numberBits

Layer2QuantClass **_quantClasses

}

/ / 27 активних піддіапазонів

/ / Для моно потрібно 88 біт для запису таблиці розподілу Layer2BitAllocationTableEntry Layer2AllocationB2a [32] = {

{ 4, l2allocationA }, { 4, l2allocationA }, { 4, l2allocationA },

{ 4, l2allocationB }, { 4, l2allocationB }, { 4, l2allocationB },

{ 4, l2allocationB }, { 4, l2allocationB }, { 4, l2allocationB },

{ 4, l2allocationB }, { 4, l2allocationB }, { 3, l2allocationC },

{ 3, l2allocationC }, { 3, l2allocationC }, { 3, l2allocationC },

{ 3, l2allocationC }, { 3, l2allocationC }, { 3, l2allocationC },

{ 3, l2allocationC }, { 3, l2allocationC }, { 3, l2allocationC },

{ 3, l2allocationC }, { 3, l2allocationC }, { 2, l2allocationD },

{ 2, l2allocationD }, { 2, l2allocationD }, { 2, l2allocationD },

{ 0,0},  { 0,0},   { 0,0}, { 0,0},    { 0,0}

}

/ / 30 активних піддіапазонів

/ / Для моно потрібно 94 біта для запису таблиці розподілу

/ / Використано при найвищих швидкостях передачі Layer2BitAllocationTableEntry Layer2AllocationB2b [32] = {

{4, l2allocationA }, { 4, l2allocationA }, { 4, l2allocationA },

{4, l2allocationB }, { 4, l2allocationB }, { 4, l2allocationB },

{4, l2allocationB }, { 4, l2allocationB }, { 4, l2allocationB },

{4, l2allocationB }, { 4, l2allocationB }, { 3, l2allocationC },

{3, l2allocationC }, { 3, l2allocationC }, { 3, l2allocationC },

{3, l2allocationC }, { 3, l2allocationC }, { 3, l2allocationC },

{3, l2allocationC }, { 3, l2allocationC }, { 3, l2allocationC },

{3, l2allocationC }, { 3, l2allocationC }, { 2, l2allocationD },

{2, l2allocationD }, { 2, l2allocationD }, { 2, l2allocationD ),

{2, l2allocationD }, { 2, l2allocationD }, { 2, l2allocationD },

{ 0,0},  { 0,0}

}

/ / 7 активних піддіапазонів

/ / Для моно потрібно 26 біт для запису таблиці розподілу

/ / Використано при найнижчих швидкостях передачі Layer2BitAllocationTableEntry Layer2AllocationB2c [32] = {

{ 4, l2allocationE }, { 4, l2allocationE },   { 3, l2allocationE },

{ 3, l2allocationE }, { 3, l2allocationE },   { 3, l2allocationE },

{ 3, l2allocationE }, { 3, l2allocationE },

{0,0},{0,0},{0,0},{0,0} , {0,0} , {0,0} , {0,0} , {0,0} ,

{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0} , {0,0} ,

{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},

}

/ / 11 активних піддіапазонів

/ / Для моно потрібно 38 біт для запису таблиці розподілу

/ / Використано при найнижчих швидкостях передачі Layer2BitAllocationTableEntry Layer2AllocationB2d [32] = {

{ 4, l2allocationE }, { 4, l2allocationE }, { 3, l2allocationE },

{ 3, l2allocationE }, { 3, l2allocationE }, { 3, l2allocationE },

{ 3, l2allocationE }, { 3, l2allocationE }, { 3, l2allocationE },

{ 3, l2allocationE }, { 3, l2allocationE }, { 3, l2allocationE },

{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},

{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},

}

/ / 30 активних піддіапазонів

/ / Для моно потрібно 7 5 біт для запису таблиці розподілу

/ / Використано для формату MPEG-2 при низьких частотах дискретизації

Layer2BitAllocationTableEntry Layer2AllocationB1[32] = {

{ 4, l2allocationF }, { 4, l2allocationF }, { 4, l2allocationF },

{ 4, l2allocationF }, { 3, l2allocationE }, { 3, l2allocationE },

{ 3, l2allocationE }, { 3, l2allocationE }, { 3, l2allocationE },

{ 3, l2allocationE }, { 3, l2allocationE }, { 2, l2allocationE },

{ 2, l2allocationE }, { 2, l2allocationE }, { 2, l2allocationE },

{ 2, l2allocationE }, { 2, l2allocationE }, { 2, l2allocationE },

{ 2, l2allocationE }, { 2, l2allocationE }, { 2, l2allocationE },

{ 2, l2allocationE }, { 2, l2allocationE }, { 2, l2allocationE },

{ 2, l2allocationE }, { 2, l2allocationE }, { 2, l2allocationE },

{ 2, l2allocationE }, { 2, l2allocationE }, { 2, l2allocationE },

{0,0},{0,0}

}

Щоб вважати величини розподілу, необхідно правильно вибрати карту розподілу на основі відомих ID, швидкості передачі бітів і частоти дискретизації Після вибору карти для визначення потрібної кількості зчитувальних бітів використовується поле _numberBits елемента відповідної комірки карти розподілу

Лістинг 1427 Layer 2: зчитування величини розподілу

/ / Визначаємо, яку карту розподілу використовувати Layer2BitAllocationTableEntry * allocationMap

long bitRatePerChannel = _bitRate/_charmels

if (_id == 0) / / Використовуємо карту розподілу MPEG-2 allocationMap = Layer2AllocationB1

else if(bitRatePerChannel &lt= 48000) {

if(_samplingRate == 32000) allocationMap = Layer2AllocationB2d

else allocationMap = Layer2AllocationB2c

} else if (bitRatePerChannel &lt 96000)

allocationMap = Layer2AllocationB2a

else if (_samplingRate == 48000)

allocationMap = Layer2AllocationB2a

else

allocationMap = Layer2AllocationB2b

/ / Зауваження: заголовок фрейма встановлює

/ / _bound В 0 для одноканальних записів, тому

/ / Пропонована програма коректно працює

/ / І для моно, і для стерео

int sblimit = 0 / / Збільшений на 1 номер старшого піддіапазону

/ / На непустому розподілом

{/ / Отримуємо окремі розподілу для повних

/ / Стереоподдіапазонов for (int sb = 0 sb <_bound; sb + +) {

if(allocationMap[sb]_numberBits) {

allocation[0][sb] = GetBits(allocationMap[sb]_numberBits)

allocation[1][sb] = GetBits(allocationMap[sb]_numberBits)

if( (allocation[0][sb] || allocation[1][sb])

&amp&amp(sb &gt= sblimit) )

sblimit=sb+1

} else {

allocation[0][sb] = 0

allocation[1][sb] = 0

}

}

}

{/ / Отримуємо загальний розподіл для піддіапазонів

/ / З інтенсивністю стерео for (int sb = _bound sb <32; sb + +) {

if(allocationMap[sb]_numberBits) {

allocation[0][sb] = GetBits(allocationMap[sb]_numberBits)

if(allocation[0][sb] &amp&amp (sb &gt= sblimit))

sblimit=sb+1

} else

allocation[0][sb] = 0

allocation[1][sb] = allocation[0][sb]

}

}

До речі, я зібрав корисні статистичні відомості Зазвичай частина високочастотних діапазонів не записуватиме зовсім Визначаючи старший діапазон, використовуваний в цьому фреймі, можна заощадити на майбутніх обчисленнях

Масштабні коефіцієнти в Layer 2

Layer 1 увазі зберігання одного набору масштабних коефіцієнтів для кожного кадру з 384 відліків Оскільки у стандарті Layer 2 відліків втричі більше, в ньому використовується ряд прийомів для більш економного зберігання масштабних коефіцієнтів

Один фрейм Layer 2 містить 36 наборів відліків піддіапазону Інакше кажучи, для кожного піддіапазону один фрейм містить 36 відліків Bo фреймі 1 Layer один масштабний коефіцієнт застосовується до всіх отсчетам одного піддіапазону Так як відліків у нас втричі більше, то для Layer 2 передбачений варіант збереження трьох масштабних коефіцієнтів (одного для кожної групи по 12), завдяки чому економиться місце

Щоб вважати масштабні коефіцієнти, спочатку витягується інформація за їх вибором Ці 2-бітові значення показують, як зберігаються масштабні коефіцієнти Потім для кожного піддіапазону ви зчитуєте або один масштабний коефіцієнт (який застосовується до всіх 36 отсчетам), або два (один застосовується до 12, інший до 24 отсчетам), або три (один на кожну группупо 12)

Лістинг 1428 Layer2: зчитування коефіцієнти множення

int scaleFactorSelection[2][32]

{/ / Прочитуємо інформацію про розташування масштабних

/ / Коефіцієнтів

for(int sb=0 sb&ltsblimit sb++)

for(int ch=0 ch&lt_channels ch++)

if(allocation[ch][sb] = 0)

scaleFactorSelection[ch][sb] = GetBits(2)

}

{

//

Прочитуємо масштабні коефіцієнти Масив

//

scaleFactorSelection використовується для того,

//

щоб визначити, який коефіцієнт відноситься більш ніж

//

до однієї групи

for(int sb=0 sb&ltsblimit sb++)

for(int ch=0 ch&lt_channels ch++)

if(allocation[ch][sb] = 0) {

switch(scaleFactorSelection[ch][sb]) {

case 0: / / Три масштабних коефіцієнта

scaleFactor[0][ch][sb] = GetBits(6) scaleFactor[1][ch][sb] = GetBits(6) scaleFactor[2][ch][sb] = GetBits(6)

break

case 1: / / Один для перших двох частин,

/ / Третій для останньої

scaleFactor[0][ch][sb] = GetBits(6) scaleFactor[1][ch][sb] = scaleFactor[0][ch][sb] scaleFactor[2][ch][sb] = GetBits(6)

break

case 2: / / Один для всіх трьох

scaleFactor[0][ch][sb] = GetBits(6) scaleFactor[1][ch][sb] = scaleFactor[0][ch][sb] scaleFactor[2][ch][sb] = scaleFactor[0][ch][sb] break

case 3: / / Один для першої частини,

/ / Один для решти двох

scaleFactor[0][ch][sb] = GetBits(6) scaleFactor[1][ch][sb] = GetBits(6) scaleFactor[2][ch][sb] = scaleFactor[1][ch][sb] break

}

}

}

Читання вибірок в Layer 2

Крім розбиття 36 наборів відліків на трійки з метою виділення масштабних коефіцієнтів у форматі Layer 2 також передбачено обєднання відліків в набори по три Замість читання одного набору з 32 відліків піддіапазонів за один раз, як зроблено в Layer I, в Layer 2 зберігаються три відліку для кожного піддіапазону Основна економія тут йде за рахунок групування

При групуванні три окремих відліку записуються в єдине бітове поле Наприклад, якщо ви хочете зберегти три значення в діапазоні від 0 до +4 .. замість використання трьох біт на кожне значення (В сумі це дає 9 біт) можна застосувати пятирічну арифметику для комбінування їх в одному

7-бітному поле

Якщо три значення це а, b, і с, то ми зберігаємо значення 25a+5b+c Для виділення цих згрупованих величин необхідно провести послідовне обчислення залишків

Лістинг 1429 Layer 2: зчитування і декодування відліків поддиапазонов

for (int sb = 0 sb

/ / Відліків піддіапазонів

for(int ch=0ch&lt_channelsch++) {

/ / Якщо обробляється поддіапазон інтенсивності стерео,

/ / То копіюємо відліки if ((sb> = _bound) && (ch == 1)) {

sbSamples[0][1][sb] = sbSamples[0][0][sb] sbSamples[1][1][sb] = sbSamples[1][0][sb] sbSamples[2][1][sb] = sbSamples[2][0][sb] continue

}

Layer2QuantClass *quantClass

= allocationMap[sb]_quantClasses

allocationMap[sb]_quantClasses[

allocation[ch][sb] ]

: 0

if ( allocation [ch] [sb]) {/ / Відсутність бітів, записуємо

/ / 0 для кожного значення sbSamples [0] [ch] [sb] = 0

sbSamples[1][ch][sb] = 0

sbSamples[2][ch][sb] = 0

} Else if (quantClass-> _grouping) {/ / Згруповані

/ / Відліки

long s = GetBits (quantClass-> _bits) / / Прочитуємо групи

/ / Виділяємо

/ / Значення,

/ / Послідовно

/ / Обчислюючи залишки

sbSamples[0][ch][sb]

= Layer2Requant(s % quantClass-&gt_levels,quantClass, scaleFactor[sf][ch][sb])

s /= quantClass-&gt_levels

sbSamples[1][ch][sb]

= Layer2Requant(s % quantClass-&gt_levels,quantClass, scaleFactor[sf][ch][sb])

s /= quantClass-&gt_levels

sbSamples[2][ch][sb]

= Layer2Requant(s % quantClass-&gt_levels,quantClass, scaleFactor[sf][ch][sb])

} Else {/ / несгруппірованних значення

int width = quantClass-&gt_bits

long s = GetBits (width) / / Перше значення sbSamples [0] [ch] [sb]

= Layer2Requant(s,quantClass,scaleFactor[sf][ch][sb])

s = GetBits (width) / / Друге значення

sbSamples[1][ch][sb]

=

Layer2Requant (s, quantClass, scaleFactor [sf] [ch] [sb]) s = GetBits (width) / / Третє значення sbSamples [2] [ch] [sb]

=

Layer2Requant(s,quantClass,scaleFactor[sf][ch][sb])

}

}

}

/ / A тепер передаємо три набори

/ / Відліків поддиапазонов

/ / В модуль синтезу

for(int ch=0ch &lt _channelsch++) { Layerl2Synthesis(_V[ch],sbSamples[0][ch],sblimit,_pcmSamples[ch])

_pcmSamples[ch] += 32 Layerl2Synthesis(_V[ch],sbSamples[1][ch],sblimit,_pcmSamples[ch])

_pcmSamples[ch] += 32 Layerl2Synthesis(_V[ch],sbSamples[2][ch],sblimit,_pcmSamples[ch])

_pcmSamples[ch] += 32

}

_samplesRemaining += 96

Передискретизація в Layer 2

Тепер набуває сенсу вміст структури Layer2QuantClass Записана в ній інформація повідомляє про те, скільки бітів повинно бути прочитане для кожного піддіапазону, і чи становлять ці біти один відлік або групу з трьох

Лістинг 1430 Layer 2: таблиці класу квантування

struct Layer2QuantClass {

long _levels / / Кількість рівнів

char _bits / / Скільки бітів треба прочитати

bool _grouping / / Так -> потрібно розкласти на три вибірки

}

Клас квантування також використовується функцією Layer2Requant для передискретизації кожної вибірки Формула аналогічна тій, яка застосовується функцією Layer1Requant

Лістинг 1430 Layer 2: таблиці класу квантування (продовження)

/ / Повертає передіскретізірованное і отмасштабовані

/ / Значення у форматі 216

inline long Layer2Requant(long sample, Layer2QuantClass *quantClass, int scaleIndex) {

long levels = quantClass-&gt_levels

return (layerlScaleFactors[scaleIndex] * (((sample+sample+1 levels)&lt&lt15)/levels)

) &gt&gt 14

}

Вивчаючи наступний фрагмент програми, зверніть увагу на те, що кількість рівнів завжди на одиницю менше найближчій ступеня числа 2 (за винятком згрупованих класів) значення, що повністю складаються з одиниць, заборонені щоб уникнути появи помилкових синхрогрупи

Лістинг 1430 Layer2: таблиці класу квантування (продовження)

static Layer2QuantClass l2qc3 = {3,5,true} static Layer2QuantClass l2qc5 = {5,7,true} static Layer2QuantClass l2qc7 = {7,3,false} static Layer2QuantClass l2qc9 = {9,10,true} static Layer2QuantClass l2qcl5 = {15,4,false} static Layer2QuantClass l2qc31 = {31,5,false} static Layer2QuantClass l2qc63 = {63,6,false} static Layer2QuantClass l2qcl27 = {127,7,false} static Layer2QuantClass l2qc255 = {255,8,false} static Layer2QuantClass l2qc511 = {511,9,false}

static Layer2QuantClass l2qcl023 = {1023,10,false}

static Layer2QuantClass l2qc2047 = {2047,ll,false} static Layer2QuantClass l2qc4095 = {4095,12,false} static Layer2QuantClass l2qc8191 = {8191,13,false} static Layer2QuantClass l2qcl6383 = {16383,14,false} static Layer2QuantClass l2qc32767 = {32767,15,false} static Layer2QuantClass l2qc65535 = {65535,16,false}

Рівень Layer 3

B порівнянні з Layer 2 компресія Layer 3 набагато складніше:

 ‰  Layer 3 Ð ¿Ð ¾ Ð · Ð ² Ð ¾ Ð »Ñ ÐμÑ, Ð ² Ð ° Ñ € ьР¸ Ñ € Ð ¾ Ð ² Ð ° Ñ, ÑŒ Ñ € Ð ° Ð · Ð ¼ ÐμÑ € Ñ Ñ € ÐμÐ ¹ Ð ¼ Ð ° ÐÐ ° Ð ½ Ð ½ Ñ <Ñ .... Ð ¥ Ð ¾ Ñ, Ñ Ð · Ð ° Ð ³ Ð ¾ Ð »Ð ¾ Ð ² Ð º Ð ¸ Ð ² Ñ ÐμÐ ³ Ð'Ð ° Ñ € Ð ° Ñ Ð ¿Ð ¾ л Ð ¾ Ð ¶ ÐμÐ ½ Ñ <Ð ½ Ð ° Ñ € Ð ° Ð ² Ð ½ Ñ <Ñ ... Ñ € Ð ° Ñ Ñ Ñ, Ð ¾ Ñ Ð ½ Ð ¸ Ñ Ñ ..., Ñ Ð ² Ñ Ð · Ð ° Ð ½ Ð ½ Ñ <Ðμ Ñ Ð ½ Ð ¸ Ð ¼ Ð ¸ Ð'Ð ° Ð ½ Ð ½ Ñ <Ðμ Ð ½ Ðμ Ð ¾ Ð ± Ñ Ð · Ð ° Ñ, ÐμÐ »ÑŒÐ ½ Ð ¾ Ð'Ð ¾ л Ð ¶ Ð ½ Ñ <Ð ½ Ð ° Ñ ​​... Ð ¾ Ð'Ð ¸ Ñ, ÑŒÑ Ñ Ñ, Ð ¾ Ð »ÑŒÐ º Ð ¾ Ð ¼ ÐμÐ ¶ Ð'у Ð'Ð ² уР¼ Ñ Ð · Ð ° Ð ³ Ð ¾ л Ð ¾ Ð ² Ð º Ð ° Ð ¼ Ð ¸. Ð-Ñ, Ð ¾ сприяє тому, що компресор Layer 3 варіює розмір фрейма залежно від підлягають стисненню даних;

 ‰   Layer 3 Ð ¸ Ñ Ð ¿Ð ¾ Ð »ÑŒÐ · уÐμÑ, Ð ± Ð ¾ л ÐμÐμ Ñ Ð »Ð ¾ Ð ¶ Ð ½ Ñ <Ð ¹ Ñ Ð ¿Ð ¾ Ñ Ð ¾ Ð ± Ñ ... Ñ € Ð ° Ð ½ ÐμÐ ½ Ð ¸ Ñ Ð ¼ Ð ° Ñ ÑÑ, Ð ° Ð ± Ð ½ Ñ <Ñ ... Ð º Ð ¾ Ñ Ñ "Ñ" Ð ¸ -

циентов: біти вибору масштабного коефіцієнта можуть застосовуватися

до груп масштабних коефіцієнтів коди масштабних коефіцієнтів мають різну довжину для різних піддіапазонів частот

 ‰   Р¾ Ñ, Ñ Ñ ‡ ÐμÑ, Ñ <Ñ Ð ¾ Ñ ... Ñ € Ð ° Ð ½ Ñ ÑŽÑ, Ñ Ñ Ñ Ð ¸ Ñ Ð ¿Ð ¾ Ð »ÑŒÐ · Ð ¾ Ð ² Ð ° Ð ½ Ð ¸ ÐμÐ ¼ Ð º Ð ¾ Ð'Ð ¾ Ð ² Ð ¥ Ð ° Ñ" Ñ "Ð ¼ Ð ° Ð ½ Ð ° (Huffman), Ñ ‡ Ñ, Ð ¾ Ð ¿Ð ¾ -

зволяет для запису частіше зустрічаються значень використовувати менше бі-

тов, ніж для запису рідше зустрічаються

 ‰  Р¿Ñ € Ð ¸ Ñ Ð ¸ Ð ½ Ñ, ÐμÐ · Ðμ Ð · Ð ² уРº Ð °, Ð · Ð ° Ð ¿Ð ¸ Ñ Ð ° Ð ½ Ð ½ Ð ¾ Ð ³ Ð ¾ Ð ² Ñ Ð ¾ Ñ € Ð ¼ Ð ° Ñ, Ðμ Layer 3, Ð ¸ Ñ Ð ¿Ð ¾ Ð »ÑŒÐ · уюÑ, Ñ Ñ ÐÐ ² Ð ° Â Ñ Ñ, Ð ° Ð ¿Ð °: Ð º Ð ° Ð ¶ ÐÑ <Ð ¹ Ð ¿Ð ¾ Ð'Ð'Ð ¸ Ð ° Ð ¿Ð ° Ð · Ð ¾ Ð ½ Layer 2 Ð'Ð ¾ Ð ¿Ð ¾ Ð »Ð ½ Ð ¸ Ñ, Ðμл ьР½ Ð ¾ Ð ¿Ð ¾ Ð'Ñ € Ð ° Ð · Ð'ÐμÐ »Ñ ÐμÑ, Ñ Ñ Ð ½ Ð ° 18 частотних меж,відліки можуть групуватися по-різному для різних піддіапазонів частот

B силу цих нововведень декомпресора Layer 3 набагато складніше декомпресора Layer 2 Оскільки формат Layer 3 досить високоорганізованих, дуже мало програм-кодувальників повною мірою використовує всі його переваги B зокрема, можливість варіювати кількість даних для кожного фрейма вимагає оптимізації вимог до компресії для декількох фреймів одночасно

Лістинг 1431 Змінні для декомпресії Layer 3

private:

void Layer3Decode()

Лістинг 1432 Декодування фрейма Layer 3

void DecompressMpeg::Layer3Decode() {

/ / Декомпресія MPEG Layer 3 не підтримується

cerr &lt&lt &quotI dont support MPEG Layer 3 decompression\n"

exit(1)

}

Програма читання файлів MPEG

Аудіофайли MPEG зазвичай складаються з аудиопотока MPEG, хоча і багато інших форматів (включаючи WAVE) можуть містити дані MPEG Щоб прочитати файл, нам знадобиться, по-перше, функція, здатна перевіряти тип файлу, а по-друге, аудіокласс, конструктор якого працює з istream

Лістинг 1433 Клас для читання файлу MPEG

bool IsMpegFile(istream &ampfile)

class MpegRead: public AudioAbstract {

private:

istream &amp_stream AbstractDecompressor *_decoder

public:

MpegRead(istream &ampinput = cin)

~MpegRead()

size_t GetSamples(AudioSample *buffer, size_t numSamples)

size_t ReadBytes(AudioByte *buffer, size_t length)

void MinMaxSamplingRate(long *min, long *max, long

*preferred)

void MinMaxChannels(int *min, int *max, int *preferred)

}

MpegRead це простий приклад класу формату файлів Конструктор працює з потоком C + + istream, метод GetSamples перенаправляє запити до обeктy _decoder, a ReadBytes витягає дані з файлу

Лістинг 143 Програма mpegcpp (продовження)

bool IsMpegFile (istream & file) {fileseekg (0) / / B початок файлу long magic = ReadIntMsb (file, 2)

if ((magic &amp 0xFFF0) == 0xFFF0) return true

else return false

}

MpegRead::MpegRead(istream &ampinput):AudioAbstract(),_stream(input)

{

/ / Формат файлу: MPEG

cerr &lt&lt &quotFile Format: MPEG\n"

_decoder = new DecompressMpeg(*this)

}

MpegRead::~MpegRead() {

if (_decoder) delete _decoder

}

size_t MpegRead::GetSamples(AudioSample *buffer, size_t numSamples) {

return _decoder-&gtGetSamples(buffer,numSamples)

}

size_t MpegRead::ReadBytes(AudioByte *buffer, size_t length) {

_streamread(reinterpret_cast&ltchar *&gt(buffer),length)

return _streamgcount()

}

void MpegRead::MinMaxChannels(int *min, int *max, int *preferred)

{

_decoder-&gtMinMaxChannels(min, max, preferred)

}

void MpegRead::MinMaxSamplingRate(long *min, long *max, long

*preferred) {

_decoder-&gtMinMaxSamplingRate(min, max, preferred)

}

Джерело: Кінтцель Т Керівництво програміста по роботі зі звуком = A Programmers Guide to Sound: Пер з англ М: ДМК Пресс, 2000 432 с, іл (Серія «Для програмістів»)

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*