Библиотека lame_enc.dll. кодируем в mp3 на FreeBasic

Предыдущая тема Следующая тема Перейти вниз

Библиотека lame_enc.dll. кодируем в mp3 на FreeBasic

Сообщение  electrik в Пн Авг 17, 2009 1:48 pm

Все мы знаем очень удобный формат 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

Код:

'  Blade Type of DLL Interface for Lame encoder
'
'  Copyright (c) 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

продолжение следует

electrik

Сообщения : 394
Дата регистрации : 2008-09-02
Возраст : 36
Откуда : галактика Млечный путь, система Солнечная, планета Земля, страна россия, город Санкт Петербург

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: Библиотека lame_enc.dll. кодируем в mp3 на FreeBasic

Сообщение  electrik в Пн Авг 17, 2009 1:49 pm

пример программы. примечание: в программе за место стандартных функций вывода на экран, используется функция printf. во FreeBasic, данные функции есть в заголовочных файлах crt. c standart library functions.

файл lame.bas

Код:

' пример работы с енкодером 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

electrik

Сообщения : 394
Дата регистрации : 2008-09-02
Возраст : 36
Откуда : галактика Млечный путь, система Солнечная, планета Земля, страна россия, город Санкт Петербург

Посмотреть профиль

Вернуться к началу Перейти вниз

Предыдущая тема Следующая тема Вернуться к началу


 
Права доступа к этому форуму:
Вы не можете отвечать на сообщения