Вело-изобретателиСтатьи

Декодирование музыкального формата OGG/Vorbis на VB6

Автор:

Введение.

Множество современных игр имеют звуковое сопровождение. Как известно звук в компьютере кодируется в формате PCM. Не будут же геймдевелоперы в своих играх хранить гигантские, несжатые звуковые файлы. :)

Существуют множество форматов сжатия аудиоданных, но, на мой взгляд, для игр - лучшим является OGG Vorbis.

Постановка задачи.
Декодирование OGG файлов в PCM данные и дальнейшая их обработка в IDE VB6.

Класс OGG файла.
Для декодирования OGG файлов будем использовать кодек: vorbis.dll, который идет в комплекте с ogg.dll (работа с контейнером) и vorbisfile.dll (работа с потоком). Так как все это добро не ориентировано для работы с VB6, было решено написать порт простенького класса для работы с OGG файлами на C++. Но как организовать работу с классом из VB6? Очень просто. :)

На стороне С++ мы создадим наш класс, выделив под него память (new), затем передадим указатель на него в VB:

 
myclass* create_myclass()
{
  myclass* pClass;
  pClass = new myclass;
  return pClass;
}

Теперь, имея лишь указатель, мы можем через специальные функции "переходники" работать с нашим классом:

 
long class_summ(myclass* pClass,int* a, int* b)
{
  return pClass->summ(a,b);
}

И в конце работы просто удалим класс:

 
void class_delete(myclass* pClass)
{
  delete pClass;
}

В этой статье не будет рассматриваться работа с библиотеками ogg, vorbis, vorbisfile. На сайте уже есть хорошая статья на этот счет.

Динамическая библиотека oggvb.
В результате изучения вышеприведенной статьи была написана библиотека oggvb.dll, содержащая экспортируемые процедуры и функции:

OggFile* create_ogg()

long load_ogg_file(OggFile* pOggFile,char* FileName)

long total_pcm(OggFile* pOggFile)

void seek_pcm(OggFile* pOggFile,long pos)

long read_pcm(OggFile* pOggFile,char* data, long size)

void get_ogg_desc(OggFile* pOggFile,vorbis_info* pDesc)

void close_ogg_file(OggFile* pOggFile)

void delete_ogg(OggFile* pOggFile)

Можно заметить, как организованы функции "переходники" для класса OggFile. Но как же указатели? Как в VB6 прейдет указатель на OggFile? По сути, указатель - это обычная Long переменная, содержащая адрес компьютерной памяти. Так же в VB6 есть специальные ключевые слова, указывающие как передать аргумент функции:
ByVal - передать значение элемента.
ByRef - передать указатель на элемент.

Теперь создадим новый класс в VB6 и объявим в нем наши процедуры и функции:

Private Declare Function create_ogg Lib "oggvb" () As Long
Private Declare Function load_ogg_file Lib "oggvb" (ByVal pOggFile As Long, ByVal FileName As String) As Long
Private Declare Function total_pcm Lib "oggvb" (ByVal pOggFile As Long) As Long
Private Declare Sub seek_pcm Lib "oggvb" (ByVal pOggFile As Long, ByVal pos As Long)
Private Declare Function read_pcm Lib "oggvb" (ByVal pOggFile As Long, ByVal pData As Long, ByVal Size As Long) As Long
Private Declare Sub get_ogg_desc Lib "oggvb" (ByVal pOggFile As Long, ByVal pDesc As Long)
Private Declare Sub close_ogg_file Lib "oggvb" (ByVal pOggFile As Long)
Private Declare Sub delete_ogg Lib "oggvb" (ByVal pOggFile As Long)

Единственной переменной, которую мы будем хранить в этом классе - будет указатель на наш класс OggFile. Для корректной работы с указателем будем отслеживать его изменение и корректно освобождать его.

Private mePtr As Long               'указатель на класс

Public Property Let Ptr(p As Long)
   If mePtr <> 0 Then delete_ogg mePtr
   mePtr = p
End Property

Public Property Get Ptr() As Long
   Ptr = mePtr
End Property

Еще нам нужно будет где-то хранить данные об файле. Для этого обьявим структуру:

Public Type MX_OGG_DESC
 Version        As Long
 Channels       As Long
 Rate           As Long
 BitrateUpper   As Long
 BitrateNominal As Long
 BitrateLower   As Long
 BitrateWindow  As Long
 CodecSetup     As Long
End Type

Чтобы  получить указатель на структуру или массив можно воспользоваться стандартной функцией VB6 VarPtr(Ptr as Any) as Long.

Теперь опишем процедуры и функции нашего класса:

'----------------------------------------------------------------------------------------------
'Загрузка файла
'----------------------------------------------------------------------------------------------
Public Function LoadOggFile(File As String) As Boolean
   If load_ogg_file(Ptr, File) = 1 Then
      LoadOggFile = True
   Else
      LoadOggFile = False
   End If
End Function

'----------------------------------------------------------------------------------------------
'Получение размера PCM данных
'----------------------------------------------------------------------------------------------
Public Function TotalPCM() As Long
   TotalPCM = total_pcm(Ptr)
End Function

'----------------------------------------------------------------------------------------------
'Установка позиции PCM буфера
'----------------------------------------------------------------------------------------------
Public Sub SeekPCM(pos As Long)
   seek_pcm Ptr, pos
End Sub

'----------------------------------------------------------------------------------------------
'Чтение из PCM буффера
'----------------------------------------------------------------------------------------------
Public Function ReadPCM(pData As Long, Size As Long) As Long
   ReadPCM = read_pcm(Ptr, pData, Size)
End Function

'----------------------------------------------------------------------------------------------
'Получение данных о файле
'----------------------------------------------------------------------------------------------
Friend Function GetDesc() As MX_OGG_DESC
Dim desc As MX_OGG_DESC

   get_ogg_desc Ptr, VarPtr(desc)
   
   GetDesc = desc
End Function

'----------------------------------------------------------------------------------------------
'Закрыть файл
'----------------------------------------------------------------------------------------------
Public Sub CloseOggFile()
   close_ogg_file Ptr
End Sub

Перед тем как приступить к использованию класса, необходимо добавить конструктор и деструктор класса:

Private Sub Class_Initialize()
   Ptr = create_ogg
End Sub

Private Sub Class_Terminate()
   If Ptr <> 0 Then
      delete_ogg Ptr
   End If
End Sub

Использование.

Работать с классом, необходимо следующим образом:
1)Создание нового экземпляра класса
2)Открытие файла
3)Получение данных о файле
4)Чтение PCM данных
5)Закрытие файла
6)Удаление экземпляра класса

Во второй части статьи будет рассмотрено практическое использование этой библиотеки.

Страницы: 1 2 Следующая »

#DirectX Sound, #OGG, #vb6

3 декабря 2011