Ваше приложение может работать с RIFF-файлами с использованием обычных функций ввода/вывода или с помощью функций, описанных выше (что удобнее). Дополнительно в библиотеке mmsystem.dll есть функции, сильно облегчающие работу с фрагментами RIFF-файлов. Эти функции помогут вам заполнить четырехбайтовый идентификатор фрагмента, найти в файле нужный фрагмент и установить на него (или за него) текущую позицию файла, а также создать новый фрагмент в новом файле.
При формировании нового фрагмента удобна функция mmioFOURCC , с помощью которой можно создать четырехбуквенный код фрагмента из отдельных букв. Функция mmioFOURCC FOURCC mmioFOURCC( CHAR ch0, // первая буква кода CHAR ch1, // вторая буква кода CHAR ch2, // третья буква кода CHAR ch3); // четвертая буква кода
Параметры функции: ch0, ch1, ch2, ch3
Коды букв, из которых будет составлен четырехбуквенный код
Возвращаемое значение:
Возвращается значение четырехбуквенного идентификатора, который можно использовать при формировании нового фрагмента
Для формирования, например, идентификатора фрагмента "WAVE" вы можете использовать эту макрокоманда следующим образом: FOURCC fourccWaveID; fourccWaveID = mmioFOURCC('W', 'A', 'V', 'E');
В некоторых случаях может оказаться удобнее формировать четырехбуквенный идентификатор не из отдельных букв, а из строки символов. Для этого можно использовать функцию mmioStringToFOURCC . Функция mmioStringToFOURCC FOURCC mmioStringToFOURCC( LPCSTR szString, // преобразуемая строка UINT wFlags); // режим преобразования
Параметры функции: szString
Указатель на преобразуемую строку, закрытую двоичным нулем wFlags
Если указан флаг MMIO_TOUPPER , все буквы строки будут преобразованы в заглавные
Возвращаемое значение:
Возвращается значение четырехбуквенного идентификатора, который можно использовать при формировании нового фрагмента
Пример использования функции mmioStringToFOURCC: FOURCC fourccWaveID; fourccWaveID = mmioStringToFOURCC("wave", MMIO_TOUPPER);
Для создания нового фрагмента в RIFF-файле удобно использовать функцию mmioCreateChunk . Новый фрагмент создается в текущей позиции файла, открытого с помощью функции mmioOpen. Функция mmioCreateChunk UINT mmioCreateChunk( HMMIO hmmio, // идентификатор открытого файла LPMMCKINFO lpck, // указатель на структуру MMCKINFO UINT wFlags); // тип фрагмента
Параметры функции: hmmio
Идентификатор открытого файла, полученный с помощью функции mmioOpen lpck
Указатель на структуру MMCKINFO, содержащую информацию о создаваемом фрагменте wFlags
Если указан флаг MMIO_CREATERIFF , создается фрагмент "RIFF", а если MMIO_CREATELIST - создается фрагмент "LIST"
Возвращаемое значение:
При нормальном завершении возвращается нулевое значение. В противном случае возвращается код ошибки
Структура MMCKINFO и указатели на нее определены в файле mmsystem.h: typedef struct _MMCKINFO { FOURCC ckid; DWORD cksize; FOURCC fccType; DWORD dwDataOffset; DWORD dwFlags; } MMCKINFO; typedef MMCKINFO *PMMCKINFO; typedef MMCKINFO NEAR *NPMMCKINFO; typedef MMCKINFO FAR *LPMMCKINFO;
Опишем назначение отдельных полей этой структуры.
Поле | Описание |
ckid | Код, соответствующий четырехбуквенному идентификатору фрагмента |
cksize | Размер фрагмента в байтах без учета идентификатора фрагмента, поля длины фрагмента и дополнительных байтов выравнивания, которые могут находиться в конце фрагмента |
fccType | Тип фрагмента |
dwDataOffset | Смещение области данных относительно начала файла в байтах |
dwFlags | В этом поле может находиться нулевое значение или флаг MMIO_DIRTY, в последнем случае длина фрагмента может быть изменена, поэтому для ее обновления следует вызвать функцию mmioAscend. Флаг MMIO_DIRTY может быть установлен при создании фрагмента функцией mmioCreateChunk |
В приведенном ниже фрагменте кода создается новый файл, подготавливается структура MMCKINFO, а затем создается фрагмент "RIFF", для чего вызывается функция mmioCreateChunk: hFile = mmioOpen(szFileName, NULL, MMIO_CREATE | MMIO_READWRITE); if(hFile != NULL) { ck.ckid = MMIO_CREATERIFF; ck.cksize = waveiocbIn.lpWaveHdr->dwBytesRecorded + sizeof(PCMWAVEFORMAT) + 20; ck.fccType = mmioFOURCC('W', 'A', 'V', 'E'); mmioCreateChunk(hFile, (LPMMCKINFO)&ck, MMIO_CREATERIFF); }
Более подробно этот фрагмент кода будет описан позже, когда мы будем рассказывать вам о приложении WAVE, работающим с wav-файлами и звуковым адаптером на низком уровне.
Для поиска нужного фрагмента внутри RIFF-файла у вас нет необходимости выполнять побайтовое чтение файла и анализ его внутренней структуры. Найти нужный фрагмент и выполнить позиционирование относительно этого фрагмента вам помогут функции mmioDescend и mmioAscend.
Функция mmioDescend ищет заданный фрагмент начиная с текущей позиции. Если фрагмент найден, текущая позиция устанавливается на область данных. Напомним, что область данных расположена на 8 байт ближе к концу файла от начала фрагмента (рис. 2.3). Функция mmioDescend UINT mmioDescend( HMMIO hmmio, // идентификатор открытого файла LPMMCKINFO lpck, // указатель на структуру MMCKINFO // для текущего фрагмента LPMMCKINFO lpckParent, // указатель на структуру MMCKINFO // для внешнего фрагмента UINT wFlags); // режим поиска
Параметры функции: hmmio
Идентификатор открытого файла, полученный с помощью функции mmioOpen lpck
Указатель на структуру MMCKINFO, в которую будет записана информация о текущем фрагменте lpckParent
Указатель на структуру MMCKINFO, описывающую внешний фрагмент, внутри которого выполняется поиск. В качестве внешнего фрагмента могут выступать только фрагменты "RIFF" или "LIST". Этот параметр можно указывать как NULL, если внешний фрагмент отсутствует wFlags
Если указан флаг MMIO_FINDCHUNK , выполняется поиск фрагмента, заданного своим идентификатором, если MMIO_FINDLIST - выполняется поиск фрагмента внутри фрагмента "LIST", если MMIO_FINDRIFF - внутри фрагмента "RIFF".
Возвращаемое значение:
При нормальном завершении возвращается нулевое значение. В противном случае возвращается код ошибки
В приведенном ниже фрагменте кода открывается на чтение wav-файл, затем в нем выполняется поиск фрагментов "WAVE" и "fmt ": hmmio = mmioOpen((LPSTR)lpszFileName, NULL, MMIO_READ | MMIO_ALLOCBUF); if(!hmmio) return WIOERR_FILEERROR; memset(&ckRIFF, 0, sizeof(MMCKINFO)); ckRIFF.fccType = mmioFOURCC('W', 'A', 'V', 'E'); if(mmioDescend(hmmio, &ckRIFF, NULL, MMIO_FINDRIFF)) { mmioClose(hmmio,0); return WIOERR_BADFORMAT; } memset(&ckFMT, 0, sizeof(MMCKINFO)); ckFMT.ckid = mmioFOURCC('f', 'm', 't', ' '); if(mmioDescend(hmmio, &ckFMT, &ckRIFF, MMIO_FINDCHUNK)) { mmioClose(hmmio,0); return WIOERR_BADFORMAT; }
Функция mmioAscend предназначена для продвижения текущей позиции к началу следующего фрагмента. Функция mmioAscend UINT mmioAscend( HMMIO hmmio, // идентификатор открытого файла LPMMCKINFO lpck, // указатель на структуру MMCKINFO UINT wFlags); // режим поиска
Параметры функции: hmmio
Идентификатор открытого файла, полученный с помощью функции mmioOpen lpck
Указатель на структуру MMCKINFO, предварительно заполненную функцией mmioDescend или mmioCreatechunk wFlags
Параметр не используется, необходимо передавать нулевое значение.
Возвращаемое значение:
При нормальном завершении возвращается нулевое значение. В противном случае возвращается код ошибки