• VoVan © (19.03.08 05:31) [0]
    Люди, помогите, никак не могу разобраться с fmod. В коде прописал
     Module := FMUSIC_LoadSong(PChar(dlgOpen.Files[0]));
     Stream := FSOUND_Stream_Open(PChar(dlgOpen.Files[0]), ......);
    файл миди
    проигрывается поток замечательно, но вопрос в другом:
    Каким образом перегнать это в вав? Говорят, что можно взять данные из буфера и сохранить в вав. Будьте добры напишите КАК это сделать. А дальше я уж LAMEом это в мп3 перекодирую.
  • Efir (19.03.08 17:16) [1]
    Можно и сразу не сохраняя в wav кодировать в mp3 lame'ом.
  • VoVan © (19.03.08 17:32) [2]
    В LAMEе есть такая ф-ция beEncodeChunk(). Как в нее подать FMODовский поток STREAM чтобы закодировать в мп3?
  • Efir (19.03.08 17:48) [3]
    Надо fmod'ом считать данные в буфер, после передать указатель на этот буфер ф-ции beEncodeChunk(). Что-то типа:

    beEncodeChunk(beStream, SizeOfRead div 2, BufWave, BufMP3, Encoded);

    Где,
    SizeOfRead - сколько байт источника было считано
    BufWave - указатель на этот буфер
    BufMP3 - сюда пишется результат
    Encoded - сколько байт закодировано

    BufWave:PSHORT;
    BufMP3: PBYTE;
  • VoVan © (19.03.08 18:56) [4]
    Спасибо, попробую. А не объяснишь почему SizeOfRead пополам делить надо?
  • VoVan © (19.03.08 19:29) [5]
    И еще вопрос: 3-й параметр ф-ции beEncodeChunc (допустим у меня он pBuffer). Как fmod'ом считать в него данные?
  • Efir (19.03.08 20:03) [6]

    > VoVan ©   (19.03.08 18:56) [4]


    Просто этот пример для 16 бит стерео, а SizeOfRead - кол-во семплов считанного WAV файла.


    > VoVan ©   (19.03.08 19:29) [5]


    Здесь я сказать не могу, т.к. не работал с этой библиотекой. Могу только дать пример с bass'ом.
  • Efir (19.03.08 20:13) [7]
    Ан нет, не совсем я прав.

    SizeOfRead - сколько байт источника было считано
    а вот
    BufWave:PShort - 2 байта.

    Итого кол-во семплов SizeOfRead div 2.
  • VoVan © (19.03.08 20:20) [8]
    А дай плиз пример с бассом.
  • Efir (19.03.08 20:40) [9]
    function EncodeToMP3(InFile:string; OutFile:string):boolean;
    var
     Progress:Int64;

     NumSamples:DWORD; //кол-во семплов, на входе кодера
     InBufSize: DWORD; //размер буфера на входе кодера
     OutBufSize:DWORD; //размер буфера на выходе кодера

     BufWave:PSHORT; //буфер чтения источника
     BufMP3: PBYTE;  //буфер результата кодирования

     BassChan:HSTREAM;
     beStream:THBESTREAM; //поток кодера
     beConfig:TBECONFIG;

     fWrite:TFileStream;

     SizeOfRead:DWORD; //размер буфера, сколько должно быть считано
     Encoded: DWORD;   //сколько было закодировано

     ErrRes:TBeErr;
     i, WAVLeng, SampleSize:DWORD;

     s:string;
    begin
     Result:=false;
     
     BassChan:=BASS_StreamCreateFile(false, PChar(InFile), 0, 0, BASS_STREAM_DECODE);
     if BassChan=0 then begin
       BASS_StreamFree(BassChan);
       Exit;
     end;
     
     FillChar(LameConfig, SizeOf(LameConfig), 0);
     beConfig.Format.dwConfig:=BE_CONFIG_LAME;
     beConfig.Format.LHV1.dwStructVersion:=1;
     beConfig.Format.LHV1.dwStructSize:=SizeOf(LameConfig);
     beConfig.Format.LHV1.dwSampleRate:=44100;
     beConfig.Format.LHV1.dwReSampleRate:=0;
     beConfig.Format.LHV1.nMode:=BE_MP3_MODE_STEREO;
     beConfig.Format.LHV1.dwBitrate:=192;
     beConfig.Format.LHV1.dwMaxBitrate:=320;
     beConfig.Format.LHV1.nPreset:=LQP_HIGH_QUALITY;
     beConfig.Format.LHV1.dwMpegVersion:=MPEG1;
     beConfig.Format.LHV1.dwPsyModel:=0;
     beConfig.Format.LHV1.dwEmphasis:=0;
     beConfig.Format.LHV1.bPrivate:=false;
     beConfig.Format.LHV1.bCRC:=false;
     beConfig.Format.LHV1.bCopyright:=false;
     beConfig.Format.LHV1.bOriginal:=false;
     beConfig.Format.LHV1.bWriteVBRHeader:=false;
     beConfig.Format.LHV1.bEnableVBR:=false;
     beConfig.Format.LHV1.nVBRQuality:=2;
     beConfig.Format.LHV1.nVbrMethod:=VBR_METHOD_NONE;
     beConfig.Format.LHV1.dwVbrAbr_bps:=0;

     WAVLeng:=BASS_ChannelGetLength(BassChan);

     ErrRes:=beInitStream(beConfig, NumSamples, OutBufSize, beStream);
     if ErrRes<>BE_ERR_SUCCESSFUL then begin
       beCloseStream(beStream);
       BASS_StreamFree(BassChan);
       Exit;
     end;

     InBufSize:=NumSamples*4;

     s:=ExtractFileName(InFile);
     OutFile:=OutFile+Copy(s, 1, Length(s)-Length(ExtractFileExt(s)))+'.mp3';
     fWrite:=TFileStream.Create(OutFile, fmCreate);
     try
       BufWave:=AllocMem(InBufSize);
       BufMP3:=AllocMem(OutBufSize);
       FillChar(BufWave^, InBufSize, 0);
       FillChar(BufMP3^, OutBufSize, 0);
       try
         i:=0;
         Progress:=0;
         while i<>WAVLeng do begin
           if i+InBufSize<WAVLeng then SizeOfRead:=InBufSize
             else SizeOfRead:=WAVLeng-i;

           BASS_ChannelGetData(BassChan, BufWave, SizeOfRead);
           ErrRes:=beEncodeChunk(beStream, SizeOfRead div 2, BufWave, BufMP3, Encoded);
           if ErrRes<>BE_ERR_SUCCESSFUL then Exit;

           fWrite.WriteBuffer(BufMP3^, Encoded);
           i:=i+SizeOfRead;
           if Terminated then Exit;
         end;

         ErrRes:=beDeinitStream(beStream, BufMP3, Encoded);
         if ErrRes<>BE_ERR_SUCCESSFUL then Exit;

         fWrite.WriteBuffer(BufMP3^, Encoded);
       finally
         fWrite.Free;
         BASS_StreamFree(BassChan);
         beCloseStream(beStream);
       end;
     finally
       FreeMem(BufWave);
       FreeMem(BufMP3);
     end;
     Result:=true;
    end;



    Но это только для кодирования файлов 44100 кГц, 16 бит, Стерео.
  • VoVan © (19.03.08 20:55) [10]
    А как бы сделать то же самое, только с миди :) ?
  • Efir (19.03.08 21:31) [11]
    Вот блин, к bass'у для работы с MIDI нужно подключать плагин, а так код остаётся тот же.
  • VoVan © (19.03.08 21:47) [12]
    А что делать с NumSamples? В миди ведь нету сэмплов. Или я что-то путаю?
  • Efir (19.03.08 23:17) [13]
    Ф-ция BASS_ChannelGetData() записывает в буфер уже декодированные данные в виде PCM.
  • VoVan © (19.03.08 23:58) [14]
    Насчет плагина. Где его взять, как его подключить и как с ним работать?
  • Efir (20.03.08 00:32) [15]
    Все добро качается с оф. сайта www.un4seen.com.
    Загрузка плагина проста, всего две функции
    BASS_PluginLoad()
    BASS_PluginFree()

    После загрузки плагина работа с потоком не меняется, он создаётся так же
    BASS_StreamCreateFile(), bass сама определяет какую библиотеку использовать при воспроизведении формата, отлично от того, кот-е поддреживает bass.dll (есс-но при условии что загружен плагин).

    В принципе работа с библиотекой достаточна проста, всё неплохо написано в хелпе к ней. К тому же, с ней идут и примеры.
  • VoVan © (20.03.08 00:43) [16]
    HPLUGIN BASS_PluginLoad(
       char *file,
       DWORD flags
    );

    здесь *file = "bassmidi.dll"?
  • Efir (20.03.08 00:58) [17]
    да
  • VoVan © (20.03.08 01:00) [18]
    Усе. Вроде бы с теорией разобрался. Огромное спасибо. Буду пытаться кодить.
  • VoVan © (20.03.08 06:22) [19]
    потестил ф-цию function EncodeToMP3(InFile:string; OutFile:string):boolean;
    вылетает(выдает ошибку) на определенной итерации цикла while.

    encoded      ...   0
    i                 ...   9216
    InBufSize     ...   4608
    OutBufSize   ...   7920
    SizeOfRead   ...   4608
    WavLeng      ...   42158

    на следующем круге i=13824, encoded=288 (все предыдущие encoded были 0) вылетает при попытке записи fWrite.WriteBufferStream
  • Efir (20.03.08 19:45) [20]
    Есть кое какие ошибки. А так работает?
    function EncodeToMP3(InFile:string; OutFile:string):boolean;
    var
    NumSamples:DWORD;
    InBufSize: DWORD;
    OutBufSize:DWORD;
    BufWave:PSHORT;
    BufMP3: PBYTE;
    BassChan:HSTREAM;
    beStream:THBESTREAM;
    beConfig:TBECONFIG;
    fWrite:TFileStream;
    SizeOfRead:DWORD;
    Encoded: DWORD;
    ErrRes:TBeErr;
    i, WAVLeng:DWORD;
    begin
    Result:=false;

    BassChan:=BASS_StreamCreateFile(false, PChar(InFile), 0, 0, BASS_STREAM_DECODE);
    if BassChan=0 then begin
      BASS_StreamFree(BassChan);
      Exit;
    end;

    FillChar(beConfig, SizeOf(beConfig), 0);
    beConfig.Format.dwConfig:=BE_CONFIG_LAME;
    beConfig.Format.LHV1.dwStructVersion:=1;
    beConfig.Format.LHV1.dwStructSize:=SizeOf(beConfig);
    beConfig.Format.LHV1.dwSampleRate:=44100;
    beConfig.Format.LHV1.dwReSampleRate:=0;
    beConfig.Format.LHV1.nMode:=BE_MP3_MODE_STEREO;
    beConfig.Format.LHV1.dwBitrate:=192;
    beConfig.Format.LHV1.dwMaxBitrate:=320;
    beConfig.Format.LHV1.nPreset:=LQP_HIGH_QUALITY;
    beConfig.Format.LHV1.dwMpegVersion:=MPEG1;

    WAVLeng:=BASS_ChannelGetLength(BassChan);

    ErrRes:=beInitStream(beConfig, NumSamples, OutBufSize, beStream);
    if ErrRes<>BE_ERR_SUCCESSFUL then begin
      beCloseStream(beStream);
      BASS_StreamFree(BassChan);
      Exit;
    end;

    InBufSize:=NumSamples*4;

    fWrite:=TFileStream.Create(OutFile, fmCreate);
    try
      BufWave:=AllocMem(InBufSize);
      BufMP3:=AllocMem(OutBufSize);
      try
        i:=0;
        while i<>WAVLeng do begin
          if i+InBufSize<WAVLeng then SizeOfRead:=InBufSize
            else SizeOfRead:=WAVLeng-i;

          BASS_ChannelGetData(BassChan, BufWave, SizeOfRead);
          ErrRes:=beEncodeChunk(beStream, SizeOfRead div 2, BufWave, BufMP3, Encoded);
          if ErrRes<>BE_ERR_SUCCESSFUL then Exit;

          fWrite.WriteBuffer(BufMP3^, Encoded);
          i:=i+SizeOfRead;
        end;

        ErrRes:=beDeinitStream(beStream, BufMP3, Encoded);
        if ErrRes<>BE_ERR_SUCCESSFUL then Exit;

        fWrite.WriteBuffer(BufMP3^, Encoded);
      finally
        fWrite.Free;
        BASS_StreamFree(BassChan);
        beCloseStream(beStream);
      end;
    finally
      FreeMem(BufWave);
      FreeMem(BufMP3);
    end;
    Result:=true;
    end;

  • Efir (20.03.08 19:50) [21]
    И midi вроде норм. кодирует.
  • VoVan © (20.03.08 21:45) [22]
    Ругается на  beConfig.Format.dwConfig:=BE_CONFIG_LAME;
    исправил на  beConfig.dwConfig:=BE_CONFIG_LAME;

    и все равно выкидывает на
     fWrite.WriteBuffer(BufMP3^, Encoded);

    А у тебя работает нормально?
  • VoVan © (20.03.08 22:50) [23]
    После вызова
        ErrRes:=beEncodeChunk(beStream, SizeOfRead div 2, BufWave, BufMP3, Encoded);
    переменные
        InBufSize и OutBufSize принимают какие-то странно большие значения
        Encoded при каждом новом запуске проги разные
  • Efir (20.03.08 22:51) [24]
    Да. А у тебя какие заголовочные файлы к lame_enc.dll, от TLame?
  • VoVan © (20.03.08 23:15) [25]
    чуть другие. А откуда скачать от TLame?
  • Efir (20.03.08 23:23) [26]
    Можно здесь http://www.delphilab.ru/content/view/76/75/

    И ещё, вместе с исходниками Lame есть пример и для Delphi с заголовочным файлом, называется mp3export.pas

    Исходники Lame - http://sourceforge.net/project/showfiles.php?group_id=290&package_id=309
  • Efir (20.03.08 23:27) [27]
    Я брал инфу для заголовочных файлов из исходников CDex и TLame.
  • VoVan © (20.03.08 23:56) [28]
    вот у меня как раз был хедер с mp3export.pas.
    Взял от TLame, теперь заработало. Огромное спасибо.
    А в случае с миди, достаточно просто подключить плагин, или надо еще в начале выходного mp3-файла что-то прописывать?
  • Efir (21.03.08 00:40) [29]
    Достаточно просто подключить плагин. По крайней мере я попробовал кодировать с midi никаких проблем не вызвало.
  • VoVan © (21.03.08 01:02) [30]
    А у меня вот какая проблема: при кодированиии вав все отлично, а миди вроде кодируется тоже нормально, но когда я его воспроизвожу звука почему-то нет.
Есть новые Нет новых   [133929   +473][b:0.001][p:0.004]