Главная » Программирование звука » Аудио MPEG структура и примеры

0

B  оставшейся  части  этой  главы  мы  сконцентрируем  внимание  на  аудиоспецификации  третьей  части  MPEG-I.  Чтобы  проиллюстрировать  обсуждаемые  принципы,  я  предполагаю  разработать  программу,  в  полной  мере  реализующую  механизм декомпрессии звука первого и второго уровней.

B  стандарте  MPEG  используется  подход,  отличный  от  подходов,  применяемых  при  создании  других  стандартов.  Третья  часть  MPEG  детально  описывает соответствующий  MPEG-формат  двоичного  потока,  однако  в  ней  не  описывается метод компрессии. Сначала это может показаться странным, однако на самом деле речь идет о важном свойстве стандарта.

Двоичный  поток  MPEG,  по  сути,  определяет  спектральный  состав  звука  и  его изменение с течением  времени. Для экономии места компрессор выборочно отбрасывает  информацию.  Стандарт  описывает,  как  кодируется  остающаяся  информация  и  как  декомпрессор  может  восстановить  выборки  ИКМ  на  основе  данных  из потока битов в кодировке MPEG. Так как процесс кодирования в стандарт не включен,  разработчики  могут  свободно  пользоваться  разнообразными  методами,  чтобы определить,  какая  информация  является  важной.  Среди  этих  методов  могли  бы встретиться  упрощенные  кодировщики  для  приложений,  работающих  со  звуком низкого  качества, или  кодировщики,  предназначенные  для  работы  со  звуками  ocoбоготипа(например,   высококачественная   компрессия   оркестровой   музыки,   скорее всего, будет отличаться от высококачественной компрессии разговорной речи).

Общая структура

Подобно   многим   аппаратно-ориентированным   алгоритмам   компрессии,   сжатые  данные  в  формате  MPEG  определяются  как  поток  битов.  K  счастью  для  разработчиков  программного  обеспечения,  опорные  точки  в  этом  потоке  битов  должны размещаться на границах байтов.

Поток  двоичной  информации  в  формате  MPEG  состоит  из  фреймов  сжатых данных. B каждом фрейме есть заголовок, в котором определяется формат этих данных.  Чтобы  декодировать  данные,  необходимо  проследить  за  принимаемыми  байтами,  идентифицировать  и  проанализировать  заголовки  фреймов,  а  полученную  из заголовков информацию использовать для декомпрессии отдельных блоков.

Листинг 14.1. Программа mpeg.h

#ifndef MPEG_H_INCLUDED

#define MPEG_H_INCLUDED

#include "audio.h"

#include "compress.h"

class DecompressMpeg: public AbstractDecompressor {

private:

private:

AudioSample _sampleStorage[2][1152];

AudioSample *_pcmSamples[2];   // Отсчеты для  левого/правого

// каналов,

int _samplesRemaining;          // Количество  оставшихся

// от последнего  фрейма отсчетов.

void NextFrame();               // Чтение  и  декомпрессия

// очередного фрейма.

public:

DecompressMpeg(AudioAbstract &a);

~DecompressMpeg();

size_t GetSamples(AudioSample *outBuff, size_t len);

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

{

*min=*max=*preferred=_samplingRate;

};

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

*min=*max=*preferred=_channels;

};

};

#endif

Общедоступные   части   класса   DecompressMpeg не   являются   патентованными.  Метод  GetSamples,  например,  копирует  отсчеты  из  буферов  выборок,  вызывая для их повторного заполнения метод NextFrame.

Листинг 14.2. Метод GetSamples для формата MPEG

size_t DecompressMpeg::GetSamples(AudioSample *outBuff, size_t wanted) {

long remaining = wanted;

while(remaining > O) {

if(_samplesRemaining == 0) { // Буфер  пуст?

NextFrame(); // Получаем  порцию   данных из  потока  MPEG.

if(_samplesRemaining == 0) // Данные   кончились?

return wanted-remaining;

}

switch(_channels) {

case 1: // Моно, просто  копируем левый канал.

while((_samplesRemaining > 0) && (remaining > O)) {

*outBuff++ = *_pcmSamples[0]++;

_samplesRemaining–;

remaining–;

}

break;

case 2:                      // Стерео, копируем оба  канала. while((_samplesRemaining > 0) && (remaining > 0)) {

*outBuff++ = *_pcmSamples[0]++;      // Левый.

*outBuff++ = *_pcmSamples[l]++;      // Правый.

_samplesRemaining–;

remaining = 2;

}

break;

}

}

return wanted-remaining;

}

Этот метод имеет достаточно сложный механизм. B оставшейся части данной главы мы обсудим отдельные компоненты этого механизма более подробно.

Листинг 14.3. Программа mpeg.cpp

#include <iostream>  // #include <iostream.h> для старых версий компиляторов.

#include <cstring>   // #include <string.h> для старых версий компиляторов.

#include <cmath>     // #include <math.h> для старых версий компиляторов.

#include <cstdio>    // #include <stdio.h> для старых версий

компиляторов.

#include "audio.h"

#include "compress.h"

#include "mpeg.h"

NextFrame(); // Читаем  первый  фрейм

// Кодировка: MPEG-.

cerr << "Encoding: MPEG-" << ((_id==0)?"2":"1");

// Уровень.

cerr << " Layer " << static_cast<int>(_layer);

cerr << "\n";

// Частота дискретизации.

cerr << "Sampling Rate: " << _samplingRate << "\n";

switch(_mode) {

// Тип: Стерео.

case 0: cerr << "Mode: Stereo\n"; break;

// Тип: Объединенный  стерео.

case 1: cerr << "Mode: Joint Stereo\n"; break;

// Тип: Двухканальный.

case 2: cerr << "Mode: Dual Channel\n"; break;

// Тип: Одноканальный.

case 3: cerr << "Mode: Single Channel\n"; break;

}

// Скорость  передачи   битов.

cerr << "Bitrate: " << _bitRate << "\n";

switch(_emphasis) {

// Предыскажение: нет.

case 0: cerr << "Emphasis: none\n"; break;

// Предыскажение: 50/15.

case 1: cerr << "Emphasis: 50/15\n"; break;

// Предыскажение: зарезервировано.

case 2: cerr << "Emphasis: reserved\n"; break;

// Предыскажение: ITU J.17.

case 3: cerr << "Emphasis: ITU J.17\n"; break;

}

// Степень  сжатия  (приблизительно):

fprintf(stderr,"Approximate Compression Ratio: %5.1f:1\n",

_samplingRate*16.0*_channels/_bitRate);

}

// Деструктор.

DecompressMpeg::~DecompressMpeg() {

}

Источник: Кинтцель Т.  Руководство программиста по работе со звуком = A Programmer’s Guide to Sound: Пер. с англ. М.: ДМК Пресс, 2000. 432 с, ил. (Серия «Для программистов»).

По теме:

  • Комментарии