AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

bassenc recording

Ein Thema von Oswin32 · begonnen am 1. Sep 2012 · letzter Beitrag vom 4. Sep 2014
Antwort Antwort
Oswin32

Registriert seit: 4. Jul 2004
8 Beiträge
 
#1

bassenc recording

  Alt 1. Sep 2012, 18:12
hi,

ich habe mir das schöne beispiel von bassenc angeguckt es funktioniert so wie es ist wunderbar

was ich aber nun möchte ist das ich mir den "mp3/ogg codierten stream / buffer" hole..

dazu hoffte ich ganz einfach die callbackfunktion in BASS_RecordStart zu nutzen


Code:
  // start recording @ 44100hz 16-bit stereo (paused to add encoder first)
  rchan := BASS_RecordStart(44100, 2, BASS_RECORD_PAUSE, @RecordingCallback, 0);
  if rchan = 0 then
  begin
    Error('Couldn''t start recording');
    Exit;
  end;
dazu habe ich mal testhalber geguckt was im buffer so drin is..

Code:
function RecordingCallback(channel: HRECORD; buffer: Pointer; length, user: DWORD): Boolean; stdcall;
begin
  Result := Bool(BASS_Encode_IsActive(channel)); // continue recording if encoder is alive
  //  Form1.lbl1.Caption:=IntToStr(length);
  if (buffer <> nil) then BlockWrite(ffiletest, buffer^,length);

end;
das problem is nu das buffer irgendwie nichts brauchbares hergibt die dateien sind riesig und nicht zu verwenden denn der inhalt sieht seltsam aus (wiederkehrende zeichenfolgen etc)

ich denke mir ich geh die sache volkommen falsch an.. ich weis das im beispiel eine mp3/ogg datei angelegt wird mit korrektem inhalt aber ich will einen eigenen mp3 oder besser ogg codierten buffer mit dem ich machen kann was ich will z.b. verschlüsseln oder übers netz schicken oder einfach speichern
ich weis auch das es eine cast beispiel gibt bei dem man das ganze auf ein icecast/shoutcast server laden kann aber soetwas will ich nicht haben mein dilemma ist also ich sehe wie man das ding abloaden kann, sehe das man es auf festplatte speichern kann aber ich kann nichts davon on the fly ändern..

hat jemand eine idee wie ich das mit dem codierten buffer anstellen kann?

danke euch im vorraus für eure hilfe
  Mit Zitat antworten Zitat
Oswin32

Registriert seit: 4. Jul 2004
8 Beiträge
 
#2

AW: bassenc recording

  Alt 2. Sep 2012, 11:50
so nach langem hin und her lesen hab ich es begriffen

das is der falsche callback..

BASS_RecordStart ist nicht der richtige platz um den callback für codierte daten zu erhalten..

nun das muss in der


Code:
   if (BASS_Encode_Start(rchan, commands[encoder], BASS_ENCODE_AUTOFREE {$IFDEF UNICODE} or BASS_UNICODE {$ENDIF}, @StatusProc, 0) = 0) then //...
passieren

damit die callbackfunktion richtig funktioniert muss man den encoder so einstellen das er zu stdout pin die daten verschickt das ist ganz einfach in der kommandozeile zu realisieren dazu muss nur den dateinamen nicht angeben

Zitat:
commands: array[0..1] of PAnsiChar = (
'oggenc.exe -', // oggenc (OGG) auf stdout gesetzt! wichtig der "-" muss am ende sein
'lame.exe --alt-preset standard - bass.mp3' // lame (MP3)
);

so ich poste hier mal für jeden den code der ganzen main unit von der bassenc rectest beispiel ich hab es so gemacht das ich die daten selber per blockwrite in eine datei schreibe

Code:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Bass, bassenc, mmsystem, ExtCtrls, StdCtrls, ComCtrls;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    lLevel: TLabel;
    cbInput: TComboBox;
    tbLevel: TTrackBar;
    gbFormat: TGroupBox;
    rbOGG: TRadioButton;
    rbMP3: TRadioButton;
    bRecord: TButton;
    bPlay: TButton;
    stStatus: TStaticText;
    Timer1: TTimer;
    rbACM: TRadioButton;
    mmo1: TMemo;
    lbl1: TLabel;
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure GetEncoder(Sender: TOBject);
    procedure FormCreate(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure bRecordClick(Sender: TObject);
    procedure bPlayClick(Sender: TObject);
    procedure cbInputClick(Sender: TObject);
    procedure tbLevelChange(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

const
  // with this you can dedected if the WaveFormatEx.wFormatTag is a Mp3 or OGG (e.g for the FileExtension
 
  ACM_CODEC_MP3_Tag = 85; // Lame or Fraunhofer Mp3 Codec
  ACM_CODEC_OGG_Tag = 26481; // Vorbis ACM Codec


var
  Form1: TForm1;
  win: HWND = 0;
  input: integer;
  encoder: integer; // current encoder
  acmForm: PWaveFormatEx;
  acmformlen: DWORD = 0;
  rchan: HRECORD = 0;
  chan: HSTREAM = 0;
  ffiletest : file;
  (* encoder command-lines and output files *)
 //   'oggenc.exe -o bass.ogg -', // oggenc (OGG)
  commands: array[0..1] of PAnsiChar = (
    'oggenc.exe -', // oggenc (OGG)
      'lame.exe --alt-preset standard - bass.mp3' // lame (MP3)
    );

  files: array[0..2] of PWideChar = ('bass.ogg', 'bass.mp3', 'bass.wav');
//  files: array[0..2] of PAnsiChar = ('bass.ogg', 'bass.mp3', 'bass.wav');

implementation

{$R *.dfm}

// display error messages

procedure Error(es: string);
var
  mes: string;
begin
  mes := format('%s' + #10 + '(error code: %d)', [es, BASS_ErrorGetCode()]);
  MessageBox(win, PChar(mes), 'Error', MB_OK);
end; //Error

function RecordingCallback(channel: HRECORD; buffer: Pointer; length, user: DWORD): Boolean; stdcall;
begin
  Result := Bool(BASS_Encode_IsActive(channel)); // continue recording if encoder is alive
//  Form1.lbl1.Caption:=IntToStr(length);
//if (buffer <> nil) then BlockWrite(ffiletest, buffer^,length);

end;

//callback von der aufnahme
procedure StatusProc(handle:DWORD; channel:DWORD; buffer:Pointer; length:DWORD; user:Pointer); stdcall;
begin
  Form1.lbl1.Caption:=IntToStr(length);
  BlockWrite(ffiletest, buffer^,length);
end;



procedure StartRecording();
begin
  if (chan <> 0) then // free old recording
  begin
    BASS_StreamFree(chan);
    chan := 0;
    Form1.bPlay.Enabled := False;
  end;
  // start recording @ 44100hz 16-bit stereo (paused to add encoder first)
  rchan := BASS_RecordStart(44100, 2, BASS_RECORD_PAUSE, @RecordingCallback, 0);
  if rchan = 0 then
  begin
    Error('Couldn''t start recording');
    Exit;
  end;
  // start encoding

  if encoder = 2 then
  begin
    // Check the needed Length for the AcmFormLen
    acmFormLen := BASS_Encode_GetACMFormat(0, nil, 0, nil, 0);
    // allocate the format buffer
    acmForm := AllocMem(acmFormLen);
    // select the ACM Format
    BASS_Encode_GetACMFormat(RChan, acmForm, acmFormLen, nil, BASS_ACM_DEFAULT);
    // a little Check if the ACM Dialog was cancel
    if Bass_ErrorGetCode = BASS_ERROR_ACM_CANCEL then
      exit;

    if BASS_Encode_StartACMFile(rchan, acmform, BASS_ENCODE_AUTOFREE {$IFDEF UNICODE} or BASS_UNICODE {$ENDIF}, PAnsiChar('bass.wav')) = 0 then
    begin
      Error('Couldn''t start encoding');
      BASS_ChannelStop(rchan);
      rchan := 0;
      exit;
    end;
    FreeMem(acmForm);
  end
  else
  begin

    if (BASS_Encode_Start(rchan, commands[encoder], BASS_ENCODE_AUTOFREE {$IFDEF UNICODE} or BASS_UNICODE {$ENDIF}, @StatusProc, 0) = 0) then
//old   if (BASS_Encode_Start(rchan, commands[encoder], BASS_ENCODE_AUTOFREE {$IFDEF UNICODE} or BASS_UNICODE {$ENDIF}, nil, 0) = 0) then
    begin
      Error('Couldn''t start encoding...' + #10
        + 'Make sure OGGENC.EXE (if encoding to OGG) is in the same' + #10
        + 'direcory as this RECTEST, or LAME.EXE (if encoding to MP3).');
      BASS_ChannelStop(rchan);
      rchan := 0;
      Exit;
    end;
  end; //StartRecording
  BASS_ChannelPlay(rchan, FALSE); // resume recoding

  Form1.bRecord.Caption := 'Stop';
  Form1.rbOgg.Enabled := False;
  Form1.rbMp3.Enabled := False;
  Form1.rbACM.Enabled := False;
end;

procedure StopRecording();
begin
  // stop recording & encoding

  BASS_ChannelStop(rchan);
  rchan := 0;
  // create a stream from the recording
Form1.mmo1.Lines.Add(files[0]);
Form1.mmo1.Lines.Add(files[1]);
Form1.mmo1.Lines.Add(files[2]);
//  chan := BASS_StreamCreateFile(FALSE, files[encoder], 0, 0, 0 {$IFDEF UNICODE} or BASS_UNICODE {$ENDIF});
  if (chan <> 0) then
    Form1.bPlay.Enabled := True; // enable "play" button;
  Form1.bRecord.Caption := 'Record';
  Form1.rbOgg.Enabled := True;
  Form1.rbMp3.Enabled := True;
  Form1.rbACM.Enabled := true;
end; //StopRecording

procedure UpdateInputInfo();
var
  _type: string;
  it: integer;
  level: Single;
begin
  it := BASS_RecordGetInput(input, level); // get info on the input
  Form1.tbLevel.Position := Trunc(level * 100); // set the level slider
  case (it and BASS_INPUT_TYPE_MASK) of
    BASS_INPUT_TYPE_DIGITAL: _type := 'digital';
    BASS_INPUT_TYPE_LINE: _type := 'line-in';
    BASS_INPUT_TYPE_MIC: _type := 'microphone';
    BASS_INPUT_TYPE_SYNTH: _type := 'midi synth';
    BASS_INPUT_TYPE_CD: _type := 'analog cd';
    BASS_INPUT_TYPE_PHONE: _type := 'telephone';
    BASS_INPUT_TYPE_SPEAKER: _type := 'pc speaker';
    BASS_INPUT_TYPE_WAVE: _type := 'wave/pcm';
    BASS_INPUT_TYPE_AUX: _type := 'aux';
    BASS_INPUT_TYPE_ANALOG: _type := 'analog';
  else
    _type := 'undefined';
  end;
  Form1.lLevel.Caption := _type; // display the type
end; //UpdateInputInfo

procedure TForm1.GetEncoder(Sender: TOBject);
begin
  Encoder := TRadioButton(Sender).Tag;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 CloseFile(ffiletest);
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  c: integer;
  dName: PAnsiChar;
  level: Single;
begin
AssignFile( ffiletest, (ExtractFilePath(ParamStr(0)))+'test.ogg');
Rewrite(ffiletest,1);
  Caption := 'BASS recording to OGG/MP3 test';

   // check the correct BASS was loaded
   if (HIWORD(BASS_GetVersion) <> BASSVERSION) then
   begin
      MessageBox(0,'An incorrect version of BASS.DLL was loaded',0,MB_ICONERROR);
      Halt;
   end;

  win := Handle;
  // setup recording and output devices (using default devices)
  if (not BASS_RecordInit(-1)) or (not BASS_Init(-1, 44100, 0, win, nil)) then
  begin
    Error('Can''t initialize device');
    Close();
  end
  else // get list of inputs
  begin
    tbLevel.Min := 0;
    tbLevel.Max := 100; // initialize input level slider
    c := 0;
    dName := BASS_RecordGetInputName(c);
    while dName <> nil do
    begin
      cbInput.Items.Add(StrPas(dName));
      if (BASS_RecordGetInput(c, level) and BASS_INPUT_OFF) = 0 then // this 1 is currently "on"
      begin
        input := c;
        cbInput.ItemIndex := c;
        UpdateInputInfo(); // display info
      end;
      inc(c);
      dName := BASS_RecordGetInputName(c);
    end; //while
    rbACM.Checked := True; // set default encoder to OGG
    Timer1.Interval := 200; // timer to update the position display
  end;
  stStatus.Caption := '';
  bPlay.Enabled := False;
end; //FormCreate

procedure TForm1.Timer1Timer(Sender: TObject);
var
  text: string;
begin
  // update the recording/playback counter
  if (rchan <> 0) then // recording/encoding
    text := Format('%d', [BASS_ChannelGetPosition(rchan, BASS_POS_BYTE)])
  else if (chan <> 0) then
  begin
    if (BASS_ChannelIsActive(chan) <> 0) then // playing
      text := Format('%d / %d', [BASS_ChannelGetPosition(chan, BASS_POS_BYTE), BASS_ChannelGetLength(chan, BASS_POS_BYTE)])
    else
      text := Format('%d', [BASS_ChannelGetLength(chan, BASS_POS_BYTE)]);
  end;
  stStatus.Caption := text;
end;

procedure TForm1.bRecordClick(Sender: TObject);
begin
  if (rchan = 0) then
    StartRecording()
  else
    StopRecording();
end;

procedure TForm1.bPlayClick(Sender: TObject);
begin
  BASS_ChannelPlay(chan, TRUE); // play the recorded data
end;

procedure TForm1.cbInputClick(Sender: TObject);
var
  i: Integer;
begin
  input := cbInput.ItemIndex; // get the selection
  // enable the selected input
  i := 0;
  while BASS_RecordSetInput(i, BASS_INPUT_OFF, -1) do
    inc(i); // 1st disable all inputs, then...
  BASS_RecordSetInput(input, BASS_INPUT_ON, -1); // enable the selected
  UpdateInputInfo(); // update info
end;

procedure TForm1.tbLevelChange(Sender: TObject);
begin
  BASS_RecordSetInput(input, 0, tbLevel.Position / 100);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  // release all BASS stuff
  BASS_RecordFree();
  BASS_Free();
end;

end.

so da können noch einige test und wuselabschnitte drin sein aber es funzt zur zeit mit dem ogg format
kompiliert und getestet auf win 7 64bit und borland delphi 2006
  Mit Zitat antworten Zitat
nuclearping

Registriert seit: 7. Jun 2008
708 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#3

AW: bassenc recording

  Alt 2. Sep 2014, 05:32
Sorry dass ich den alten Beitrag nochmal hochhole. Aber ich hab grad ein ähnliches Problem.

Nur dass der Code hier nicht (mehr?) funktioniert. Ich habe die RecTest-Demo von BassEnc genommen, dort die entsprechende ENCODEPROC-Callback-Prozedur hinzugefügt und einen Breakpoint reingesetzt. Der Breakpoint wird zwar als aktiv angezeigt, die Aufnahme läuft (keine Fehlermeldungen), ich kann sie auch wieder abspielen, aber die Callback-Funktion wird nie aufgerufen. Die RecordingCallback jedoch immer und Result ist dort auch immer True.

Delphi-Quellcode:
// **** Wird immer aufgerufen, Result immer True
function RecordingCallback(channel: HRECORD; buffer: Pointer; length, user: DWORD): Boolean; stdcall;
begin
  Result := Bool(BASS_Encode_IsActive(channel)); // continue recording if encoder is alive
end;

// **** Wird nie aufgerufen
// ENCODEPROC = procedure(handle:DWORD; channel:DWORD; buffer:Pointer; length:DWORD; user:Pointer); {$IFDEF MSWINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
procedure RecordingStatusProc(handle:DWORD; channel:DWORD; buffer:Pointer; length:DWORD; user:Pointer); stdcall;
begin
  ShowMessage('Test');
end;

// ...

rchan := BASS_RecordStart(44100, 2, BASS_RECORD_PAUSE, @RecordingCallback, 0);
if rchan = 0 then
  // ...

if (BASS_Encode_Start(rchan, commands[encoder], BASS_ENCODE_AUTOFREE {$IFDEF UNICODE} or BASS_UNICODE {$ENDIF}, @RecordingStatusProc, 0) = 0) then
  // ...
Jemand eine Idee?
  Mit Zitat antworten Zitat
nuclearping

Registriert seit: 7. Jun 2008
708 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#4

AW: bassenc recording

  Alt 3. Sep 2014, 18:44
Die Lösung hier ist, dass man, genau wie bei OGG, auch für MP3 keine Output Datei angeben darf.

Der Aufruf "lame.exe --alt-preset standard - bass.mp3" muss also auch in "lame.exe --alt-preset standard - -" geändert werden. Dann klappts.

  Mit Zitat antworten Zitat
AlexII

Registriert seit: 28. Apr 2008
1.717 Beiträge
 
FreePascal / Lazarus
 
#5

AW: bassenc recording

  Alt 3. Sep 2014, 19:48
@Oswin32
Kannst Du vllt das ganze Projekt hochladen?
Bin Hobbyprogrammierer! Meine Fragen beziehen sich meistens auf Lazarus!
  Mit Zitat antworten Zitat
nuclearping

Registriert seit: 7. Jun 2008
708 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#6

AW: bassenc recording

  Alt 3. Sep 2014, 19:52
Das ganze Projekt ist nur die RecTest-Demo direkt aus der BassEnc-Library.
  Mit Zitat antworten Zitat
AlexII

Registriert seit: 28. Apr 2008
1.717 Beiträge
 
FreePascal / Lazarus
 
#7

AW: bassenc recording

  Alt 3. Sep 2014, 19:55
Das ganze Projekt ist nur die RecTest-Demo direkt aus der BassEnc-Library.
Ok
Bin Hobbyprogrammierer! Meine Fragen beziehen sich meistens auf Lazarus!
  Mit Zitat antworten Zitat
nuclearping

Registriert seit: 7. Jun 2008
708 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#8

AW: bassenc recording

  Alt 4. Sep 2014, 02:08
Wieso? Wo hängts denn?
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:17 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz