Статистика |
Онлайн всего: 1 Гостей: 1 Пользователей: 0 |
|
Библиотека lame_enc.dll. Кодируем в mp3 на FreeBasic
Урок от electrik/Lesson by elecktrik
Все мы знаем очень удобный формат mp3. это формат звуковых файлов, с
плотной степенью сжатия, при этом, с хорошим качеством звучания. он
поддерживается почти всеми устройствами, начиная от компьютера, dvd
плеера и заканчивая наладонными системами и мобильными телефонами. есть
огромное количество программ для кодирования в mp3, например, кодек
lame, управляемый командной строкой или графической оболочкой razorlame,
программа cdex, которая использует lame_enc.dll. Вот именно о
lame_enc.dll пойдет речь. иногда бывает нужно кодировать звуковой
поток налету, например, звуковые шпионы, запись с радио, создание
аудиокниг из голосовых движков text to speech и т.д. при кодировании на
лету, желательно, чтобы компьютер обладал достаточными ресурсами. если
кодирование mp3, будет отставать от реального времени, запись
радиостанции, может быть не совсем удобной. можно понизить уровень
качества, будет быстрое кодирование, но тогда качество сжатого звука,
будет сильно отличаться от оригинала. мы же пока не будем кодировать
на лету, просто я вам покажу как работать с енкодером. данное описание
не вкоем случае не претендует на роль полного. в комментариях
заголовочного файла, будут вкратце, пояснены лишь некоторые члены
структур. сама программа почти ни чего не умеет, она лишь кодирует
wav файлы с частотой дискретизации 44100, 16 бит. даже не проверяется
заголовок wav файла, первые 44 байта пропускаются. так что если вы
захотите кодировать файл отличающийся от данных параметров, скорее
всего будут проблемы со скоростью звучания. в командной строке нужно
указать имя wav файла. программа создаст файл типа: sound.wav.mp3.
то есть, к введенному в командной строке, добавляется расширение .mp3. вы
можете скачать полный пакет, заголовочный файл+пример+интерфейсная
библиотека+сам енкодер lame_enc.dll+документация по интерфейсу енкодера
на английском языке+тестовый wav файл: http://eric50.narod.ru/freebasic/lame.zip
Заголовочный файл BladeMP3EncDLL.bi Code ' Blade Type of DLL Interface for Lame encoder ' ' Copyright © 1999-2002 A.L. Faber ' Based on bladedll.h version 1.0 written by Jukka Poikolainen ' ' This library is free software; you can redistribute it and/or ' modify it under the terms of the GNU Lesser General Public ' License as published by the Free Software Foundation; either ' version 2 of the License, or (at your option) any later version. ' ' This library is distributed in the hope that it will be useful, ' but WITHOUT ANY WARRANTY; without even the implied warranty of ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ' Lesser General Public License for more details. ' ' You should have received a copy of the GNU Lesser General Public ' License along with this library; if not, write to the ' Free Software Foundation, Inc., 59 Temple Place - Suite 330, ' Boston, MA 02111-1307, USA. ' *** adapted to FreeBasic by Electrik
#include "windows.bi" #inclib "lame_enc" #ifndef __BLADEDLL_BI__ #define __BLADEDLL_BI__ #pragma once
' форматы кодирования #define BE_CONFIG_MP3 0 #define BE_CONFIG_LAME 256
' объявление структур type as dword HBE_STREAM type as HBE_STREAM ptr PHBE_STREAM type as dword BE_ERR
' коды ошибок #define BE_ERR_SUCCESSFUL &h00000000 #define BE_ERR_INVALID_FORMAT &h00000001 #define BE_ERR_INVALID_FORMAT_PARAMETERS &h00000002 #define BE_ERR_NO_MORE_HANDLES &h00000003 #define BE_ERR_INVALID_HANDLE &h00000004 #define BE_ERR_BUFFER_TOO_SMALL &h00000005
' прочие константы #define BE_MAX_HOMEPAGE 128
' format specific variables #define BE_MP3_MODE_STEREO 0 ' стерео режим #define BE_MP3_MODE_JSTEREO 1 ' джоинт стерео #define BE_MP3_MODE_DUALCHANNEL 2 ' двойной канал #define BE_MP3_MODE_MONO 3 ' моно режим
#define MPEG1 1 ' версия мпег #define MPEG2 0 ' версия мпег. низкие битрейты и частоты дискретизации
#define CURRENT_STRUCT_VERSION 1 #define CURRENT_STRUCT_SIZE sizeof(BE_CONFIG) ' - к настоящему времени 331 байта
enum VBRMETHOD VBR_METHOD_NONE = -1 ' отключить переменный битрейт VBR_METHOD_DEFAULT = 0 VBR_METHOD_OLD = 1 VBR_METHOD_NEW = 2 VBR_METHOD_MTRH = 3 VBR_METHOD_ABR = 4 end enum
enum LAME_QUALITY_PRESET LQP_NOPRESET =-1 ' использовать без готовых предустановок
' готовые предустановки качества звука и скорости кодирования LQP_NORMAL_QUALITY = 0 ' нормальное качество LQP_LOW_QUALITY = 1 ' низкое качество LQP_HIGH_QUALITY = 2 ' высокое качество LQP_VOICE_QUALITY = 3 ' качество для голоса LQP_R3MIX = 4 LQP_VERYHIGH_QUALITY = 5 ' очень высокое качество LQP_STANDARD = 6 ' стандарт LQP_FAST_STANDARD = 7 ' стандарт, быстрое кодирование LQP_EXTREME = 8 ' предел LQP_FAST_EXTREME = 9 ' предел, быстрое кодирование LQP_INSANE = 10 ' скоростное кодирование LQP_ABR = 11 ' average bytrate LQP_CBR = 12 ' постоянный битрейт LQP_MEDIUM = 13 LQP_FAST_MEDIUM = 14
' новые готовые предустановки LQP_PHONE = 1000 ' как по телефону LQP_SW = 2000 LQP_AM = 3000 ' как средневолновый приемник LQP_FM = 4000 ' как фм радио LQP_VOICE = 5000 ' для голоса LQP_RADIO = 6000 ' радио LQP_TAPE = 7000 ' как на магнитофоне LQP_HIFI = 8000 ' хай фай LQP_CD = 9000 ' качество как у компакт диска LQP_STUDIO = 10000 ' студийное качество end enum
type MP3 field = 1 ' BE_CONFIG_MP3 as dword dwSampleRate ' допустимо 48000, 44100 и 32000 килогерц as byte byMode ' режимы каналов, BE_MP3_MODE_STEREO, BE_MP3_MODE_DUALCHANNEL, BE_MP3_MODE_MONO. см. выше as word wBitrate ' допустимо 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256 и 320 килобит as BOOL bPrivate ' флажки. часный as BOOL bCRC ' контрольная сумма as BOOL bCopyright ' авторское право as BOOL bOriginal end type
type LHV1 field = 1 ' LAME header version 1
' информация о структуре as dword dwStructVersion ' версия структуры as dword dwStructSize ' размер структуры
' базовые установки енкодера as dword dwSampleRate ' частота дискретизации для входного файла as dword dwReSampleRate ' частота- для ресемплирования, 0=выбирается енкодером as LONG nMode ' режимы каналов, BE_MP3_MODE_STEREO, BE_MP3_MODE_DUALCHANNEL, BE_MP3_MODE_MONO. см. выше as dword dwBitrate ' устанавливает постоянный битрейт, для переменного минимальный as dword dwMaxBitrate ' постоянный битрейт игнорируется, устанавливает максимальный переменный битрейт as LONG nPreset ' используйте одну из готовых предустановок LAME_QUALITY_PRESET enum as dword dwMpegVersion ' версия mpeg. используйте, MPEG-1 или MPEG-2 as dword dwPsyModel ' FUTURE USE, SET TO 0 as dword dwEmphasis ' FUTURE USE, SET TO 0
' установка флагов в поток as BOOL SbPrivate ' установить часный бит (TRUE/FALSE) as BOOL IbCRC ' вставить контрольную сумму (TRUE/FALSE) as BOOL SbCopyright ' установить бит авторское право (TRUE/FALSE) as BOOL bOriginal ' Set Original Bit (TRUE/FALSE) ' VBR STUFF as BOOL bWriteVBRHeader ' WRITE XING VBR HEADER (TRUE/FALSE) as BOOL bEnableVBR ' включить переменный битрейт (TRUE/FALSE) as INTEGER nVBRQuality ' качество при переменном битрейте 0..9 as dword dwVbrAbr_bps ' Использовать ABR вместо nVBRQuality as VBRMETHOD nVbrMethod ' метот vbr as BOOL bNoRes ' Disable Bit resorvoir (TRUE/FALSE)
' MISC SETTINGS as BOOL bStrictIso ' Use strict ISO encoding rules (TRUE/FALSE) as WORD nQuality ' установка качества, HIGH BYTE should be NOT LOW byte, otherwhise quality=5
' FUTURE USE , SET TO 0, align structure to 331 bytes as BYTE btReserved(255-4*sizeof(dword) - sizeof( WORD )-1) end type
type AAC field = 1 ' aac as dword dwSampleRate ' частота дискретизации as BYTE byMode ' режим каналов as WORD wBitrate ' битрейт as BYTE byEncodingMethod ' метод кодирования end type
union FORMAT field = 1 'format as MP3 mp3 as LHV1 lhv1 as AAC aac end union
type BE_CONFIG field = 1 as dword dwConfig ' BE_CONFIG_XXXXX ' поддерживается BE_CONFIG
as FORMAT format end type
type as BE_CONFIG ptr PBE_CONFIG
type BE_VERSION
' BladeEnc DLL номер версии as BYTE byDLLMajorVersion as BYTE byDLLMinorVersion
' BladeEnc номер версии движка (engine) as BYTE byMajorVersion as BYTE byMinorVersion
' дата релиза DLL as BYTE byDay as BYTE byMonth as WORD wYear
'BladeEnc домашняя страница as zstring * BE_MAX_HOMEPAGE + 1 zHomepage
as BYTE byAlphaLevel as BYTE byBetaLevel as BYTE byMMXEnabled
as BYTE btReserved(125-1) end type
type as BE_VERSION ptr PBE_VERSION
extern "c"
' функция инициализации потока declare function beInitStream alias "beInitStream" _ (byval pbeConfig as PBE_CONFIG, byval dwSamples as PDWORD, _ byval dwBufferSize as PDWORD, byval phbeStream as PHBE_STREAM) as BE_ERR
' функция кодирования частей данных declare function beEncodeChunk alias "beEncodeChunk" _ (byval hbeStream as HBE_STREAM, byval nSamples as DWORD, _ byval pSamples as PSHORT, byval pOutput as PBYTE, _ byval pdwOutput as PDWORD )as BE_ERR
'added for floating point audio -- DSPguru, jd declare function beEncodeChunkFloatS16NI alias "beEncodeChunkFloatS16NI" _ (byval hbeStream as HBE_STREAM, byval nSamples as DWORD, _ byval buffer_l as PFLOAT, byval buffer_r as PFLOAT, _ byval pOutput as PBYTE, byval pdwOutput as PDWORD) as BE_ERR
' функция деинициализации потока declare function beDeinitStream alias "beDeinitStream" _ (byval hbeStream as HBE_STREAM, byval pOutput as PBYTE, _ byval pdwOutput as PDWORD) as BE_ERR
' функция закрытия потока declare function beCloseStream alias "beCloseStream" _ (byval hbeStream as HBE_STREAM) as BE_ERR
' функция получения версии енкодера declare function beVersion alias "beVersion" _ (byval pbeVersion as PBE_VERSION) as PCVOID
declare function beWriteVBRHeader alias "beWriteVBRHeader" _ (byval lpszFileName as LPCSTR) as BE_ERR declare function beFlushNoGap alias "beFlushNoGap" _ (byval hbeStream as HBE_STREAM, byval pOutput as PBYTE, _ byval pdwOutput as PDWORD) as BE_ERR declare function beWriteInfoTag alias "beWriteInfoTag" _ (byval hbeStream as HBE_STREAM, byval lpszFileName as LPCSTR) as BE_ERR end extern #endif Пример программы. Примечание: в программе за место стандартных функций вывода на экран, используется функция printf. во FreeBasic, данные функции есть в заголовочных файлах crt. c standart library functions. Файл lame.bas Code ' пример работы с енкодером lame ' основано на коде " * Copyright (c) 2000 A.L. Faber" ' оптимизировал под FreeBasic electrik #include "windows.bi" #include "file.bi" #include "crt.bi" #include "BladeMp3EncDll.bi"
#define argc __fb_argc__ ' сделаем запись по удобней #define argv __fb_argv__ dim as BE_VERSION Version ' структура версии енкодера dim as BE_CONFIG beConfig ' структура параметров енкодера dim as zstring * 255 strFileIn ' имя входного wav файла dim as zstring * 255 strFileOut ' имя выходного mp3 файла dim as DWORD dwSamples ' длина raw pcm данных dim as dword dwMP3Buffer ' длина скодированных mp3 данных dim as HBE_STREAM hbeStream ' хэндл потока dim as BE_ERR beErr ' код ошибки dim as PBYTE pMP3Buffer ' буфер для скодированных mp3 данных dim as PSHORT pWAVBuffer ' буфер для raw pcm данных из wav файла dim as integer fileIn ' номер входного файла dim as integer fileOut ' номер выходного файла if argc <> 2 then ' если аргументов <> 2 считая нулевой printf(!"Usage: %s <filename.wav>\n",*argv[0]) printf(!"example: %s sound.wav\n",*argv[0]) printf(!"Descr: Short demo to show how to use the lame_enc.dll library file\n") printf(!"Note : WAV file is assumed to to have the following parameters\n") printf(!" : 44100 Hz, stereo, 16 Bits per sample\n") end -1 end if
' запишем в строки для имен файлов полученное имя из командной строки ' к строке выходного файла добавим .mp3 strFileIn = *argv[1] strFileOut = *argv[1] & ".mp3"
beVersion(@version) ' получим версию енкодера
' отобразим элементы версии енкодера из структуры BE_VERSION printf _ (!"lame_enc.dll version %u.%02u (%u/%u/%u)\n" _ !"lame_enc Engine %u.%02u\n" _ !"lame_enc homepage at %s\n\n", _ Version.byDLLMajorVersion, Version.byDLLMinorVersion, _ Version.byDay, Version.byMonth, Version.wYear, _ Version.byMajorVersion, Version.byMinorVersion, _ Version.zHomepage)
if not fileExists(strFileIn) then ' если входной .wav файл не существует printf("Error opening %s, file not exists", argv[1]) ' выдаем ошибку end -1 ' и выходим из программы end if
fileIn = FreeFile ' получим номер для входного файла open strFileIn for binary as #fileIn ' откроем в бинарном режиме fileOut = FreeFile ' получим номер для выходного файла open strFileOut for binary as #fileOut ' откроем в бинарном режиме
' заполним члены структуры be_Config beConfig.dwConfig = BE_CONFIG_LAME beConfig.format.LHV1.dwStructVersion = 1 beConfig.format.LHV1.dwStructSize = sizeof(BE_CONFIG) beConfig.format.LHV1.dwSampleRate = 44100 beConfig.format.LHV1.dwReSampleRate = 0 beConfig.format.LHV1.nMode = BE_MP3_MODE_JSTEREO beConfig.format.LHV1.dwBitrate = 128 beConfig.format.LHV1.nPreset = LQP_R3MIX beConfig.format.LHV1.dwMpegVersion = MPEG1 beConfig.format.LHV1.dwPsyModel = 0 beConfig.format.LHV1.dwEmphasis = 0 beConfig.format.LHV1.bOriginal = TRUE beConfig.format.LHV1.bWriteVBRHeader = TRUE beConfig.format.LHV1.bNoRes = TRUE
' инициализируем поток (енкодер) beErr = beInitStream(@beConfig, @dwSamples, @dwMP3Buffer, @hbeStream) if beErr <> BE_ERR_SUCCESSFUL then ' если не равно ошибке printf("Error opening encoding stream (%lu)", beErr) end -1 end if pMP3Buffer = new byte [dwMP3Buffer] ' выделим память под mp3 данные pWAVBuffer = new short[dwSamples] ' выделим память для wav данных
if pMP3Buffer = 0 then printf("not enough memory for mp3Buffer") end -1 end if
if pWAVBuffer = 0 then printf("not enough memory for wavBuffer") end -1 end if
dim as DWORD dwRead ' число прочитанных элементов dim as DWORD dwWrite ' число записываемых mp3 данных в файл dim as DWORD dwDone ' насколько выполнено dim as DWORD dwFileSize ' длина wav файла
dwFileSize = lof(fileIn) ' получим длину файла seek #fileIn,45 ' пропустим 44 байта заголовка wav файла dwRead = 1 ' просто поставим 1, чтоб цикл сработал while dwRead <> 0 ' пока недостигли конец файла
get #fileIn,,*pWAVBuffer,dwSamples,dwRead ' читаем часть wav данных if dwRead = 0 then continue while ' можно exit while
' начинаем кодирование по частям ' dwRead/sizeof(SHORT)- это чтоб передать функции не число прочитанных байт, 'а число элементов длиной типа SHORT. SHORT- это 2 байта beErr = beEncodeChunk(hbeStream, dwRead/sizeof(SHORT), pWAVBuffer, pMP3Buffer, @dwWrite)
if beErr <> BE_ERR_SUCCESSFUL then beCloseStream(hbeStream) ' если ошибка, закрываем поток printf("beEncodeChunk() failed (%lu)", beErr) end -1 end if
' пишем mp3 данные в файл if put( #fileOut,,*pMP3Buffer,dwWrite) <> 0 then printf("Output file write error") end -1 end if dwDone += dwRead
' выведем результат выполнения в процентах printf(!"Done: %0.2f%% \r", 100 * cast(SINGLE,dwDone)/cast(SINGLE,dwFileSize)) wend ' деинициализируем поток beErr = beDeinitStream(hbeStream, pMP3Buffer, @dwWrite)
if beErr <> BE_ERR_SUCCESSFUL then beCloseStream(hbeStream) ' если ошибка, закрываем поток printf("beExitStream failed (%lu)", beErr) end -1 end if
' может я не правильно перевел фразу. ' после вызова DeInit возвращаются любые байты? ' Если так, запишите их на диск ' // Are there any bytes returned from the DeInit call? ' // If so, write them to disk if dwWrite then if put( #fileOut,,*pMP3Buffer,dwWrite) <> 0 then 'printf("Output file write error") end -1 end if end if
beCloseStream( hbeStream ) ' закроем поток
' очистим память от буферов delete[] pWAVBuffer delete[] pMP3Buffer close ' закроем все открытые файлы
'beWriteInfoTag( hbeStream, strFileOut ) ' пишет какой-то тег end 0 ' вернем операционке 0
|
Категория: Basic | Добавил: Admin (06.12.2010)
|
Просмотров: 5773
| Рейтинг: 3.5/2 |
Добавлять комментарии могут только зарегистрированные пользователи. [ Регистрация | Вход ]
|
|
|