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

