AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi "bass.dll" Aufnahme an beliebiger Stelle im Stream fortsetze

"bass.dll" Aufnahme an beliebiger Stelle im Stream fortsetze

Offene Frage von "Ducksoul"
Ein Thema von Ducksoul · begonnen am 27. Aug 2008 · letzter Beitrag vom 10. Okt 2008
Antwort Antwort
Seite 2 von 2     12
Ducksoul

Registriert seit: 19. Apr 2006
Ort: Ilmenau
87 Beiträge
 
RAD-Studio 2009 Pro
 
#11

Re: "bass.dll" Aufnahme an beliebiger Stelle im St

  Alt 10. Sep 2008, 22:53
So sieht die abgeänderte Version aus. Jetzt wird der Header nicht jedes mal neu geschrieben. Das war mir heute morgen schon aufgefallen, aber das abzuändern hatte leider nichts gebracht.
Das Problem mit dem Rauschen besteht aber leider immernoch, komischerweise nicht immer, sondern nur manchmal.

Kann es sein, dass aus mir unbekannten Gründen der Stream manchmal vorhandene Daten überschreibt und daher das Rauschen entsteht? Da ich keine Ahnung habe woran das Verhalten überhaupt liegen kann, weiß ich nichmal wie ich das Problem angehen kann

Delphi-Quellcode:
  (* Aufnahme Start *)
  procedure TFormular.StartRecording;
    var
      vol: Float;
      i, RecPos: Integer;
      Flag: DWord;
    begin

      if WaveStream.Size = 0 then
        begin
         // Header für WAV-File generieren
       with WaveHdr do
        begin
            riff := 'RIFF';
            len := 36;
            cWavFmt := 'WAVEfmt ';
            dwHdrLen := 16;
            wFormat := 1;
            wNumChannels := 2;
            dwSampleRate := 44100;
            wBlockAlign := 4;
            dwBytesPerSec := 176400;
            wBitsPerSample := 16;
            cData := 'data';
            dwDataLen := 0;
        end; // with

         WaveStream.Write(WaveHdr, SizeOf(WAVHDR));
         i := 0;
        end
      else
        begin
          if Rec_Overwrite.Checked = True then
            begin
                // hier ab aktueller Position Aufnahme fortsetzen
              (*WaveStream.Seek(GetPos, soFromBeginning);

              if WaveStream.Position < SizeOf(WaveHDR) then
                WaveStream.Seek(SizeOf(WaveHDR)+1, soFromBeginning);

              WaveStream.SetSize(WaveStream.Position);
              WaveStream.Seek(0, soFromEnd);
              Edit1.Text := IntToStr(WaveStream.Size); *)


              RecPos := GetPos;
                // Zwischenspeicher anlegen
              BufStream := TMemoryStream.Create;
              BufStream.SetSize(RecPos);
                // Wavedaten in Zwischenspeicher kopieren
              Move(WaveStream.Memory^,BufStream.Memory^,RecPos);
                // WaveStream abschneiden
              WaveStream.SetSize(RecPos);
                // Wavedaten rückkopieren
              Move(BufStream.Memory^,WaveStream.Memory^,RecPos);
              BufStream.Free;
                // Position setzen
              WaveStream.Position := RecPos;
            end; // if

          if Rec_Passage.Checked = True then
            begin
                // hier an aktueller Position Passage einfügend
            end; // if
        end; // if


        vol := RecordPegelBar.Position/100;
         while BASS_RecordSetInput(i, BASS_INPUT_OFF, vol)
          do i := i + 1;


          // ---LoWord-- ----HiWord----
        Flag := MakeLong(c16BitAudio, cRecordingTime);
           // Aufnahmebeginn @ 44100hz 16-bit stereo
         rchan := BASS_RecordStart(cSamplerate,
                                  cNumChannels,
                                  Flag,
                                  @RecordingCallback,
                                  nil);

         if rchan = 0
          then begin
              MessageDlg('Aufnahme konnte nicht gestartet werden!',
                        mtError, [mbOk], 0);
              WaveStream.Clear;
           end;
    end; // procedure StartRecording
Danke trotzdem,
Duck
Franz
  Mit Zitat antworten Zitat
riko.delphipraxis

Registriert seit: 13. Aug 2008
12 Beiträge
 
#12

Re: "bass.dll" Aufnahme an beliebiger Stelle im St

  Alt 10. Sep 2008, 23:14
Wann rauscht was wo?
  Mit Zitat antworten Zitat
omata

Registriert seit: 26. Aug 2004
Ort: Nebel auf Amrum
3.154 Beiträge
 
Delphi 7 Enterprise
 
#13

Re: "bass.dll" Aufnahme an beliebiger Stelle im St

  Alt 10. Sep 2008, 23:37
Wegen Nicht-Beachtung gelöscht.
  Mit Zitat antworten Zitat
riko.delphipraxis

Registriert seit: 13. Aug 2008
12 Beiträge
 
#14

Re: "bass.dll" Aufnahme an beliebiger Stelle im St

  Alt 10. Sep 2008, 23:46
Wenn du was in deinen Wave-Stream einfügen willst nimmst du für diesen Modus am einfachsten einen neuen Stream in der Callback-Funktion.

Etwa so, ohne Funktionsgarantie...
Einfügeposition merken
InsertStream anlegen und in Callback verwenden
nach Aufnahmeende Zwischenspeicher anlegen
WaveStream bis zur Einfügeposition in Zwischenspeicher schreiben
InsertStream in Zwischenspeicher anhängen
Rest des Wavestreams in Zwischenspeicher anhängen
WaveStream Größe neu setzen
Zwischenspeicher in Wavestream rückkopieren
Länge im Wavehader anpassen

function RecordingCallback....

if Rec_Passage.Checked then
Formular.InsertStream.Write(buffer^, length)
else Formular.WaveStream.Write(buffer^, length);
...


procedure TFormular.StartRecording;
...
if Rec_Passage.Checked then
InsertPos := GetPos;
InsertStream := TMemoryStream.Create;
end if;
...


procedure TFormular.StopRecording;
...
if Rec_Passage.Checked then
begin
BufStream := TMemoryStream.Create;
BufStream.Write(WaveStream.Memory^,InsertPos);
BufStream.Write(InsertStream.Memory^,InsertStream. Size);
BufStream.Write(PByteArray(WaveStream.Memory)^[InsertPos],WaveStream.Size-InsertPos);
WaveStream.SetSize(BufStream.Size);
Move(BufStream.Memory^,WaveStream.Memory^,BufStrea m.Size);
BufStream.Free;
InsertStream.Free;
end;

// WAV-Header komplettieren
WaveStream.Position := 4;
i := WaveStream.Size - 8;
....


So ähnlich muss das klappen ohne das was rauscht...

Und ich geh jetzt auf den Federnball...
  Mit Zitat antworten Zitat
Ducksoul

Registriert seit: 19. Apr 2006
Ort: Ilmenau
87 Beiträge
 
RAD-Studio 2009 Pro
 
#15

Re: "bass.dll" Aufnahme an beliebiger Stelle im St

  Alt 11. Sep 2008, 11:09
Guten Morgen,

also mein Code sieht nun wie folgt aus, aber das Rauschen besteht immernoch. Aber mir ist eingefallen woran es eventuell liegen könnte:

(* Angenommen ich nehme was auf, dann wird am Ende ja der Waveheader komplettiert. Nehme ich was neues auf, dann wird die vorige Datei mit kompletten Waveheader genommen und der Waveheader am Ende nochmal komplettiert und so weiter und sofort. Könnte das die Ursache sein? *)

Edit: Ich habe es jetzt so gelöst, dass der WaveStream ohne komplettierten Header in einen Zwischenspeicher BufStream2 gespeichert wird und beim Zusammenführen dann aus diesem gelesen wird und nicht aus dem WaveStream mit komplettierten Header.(siehe Code) Das Problem besteht trotzdem noch...

Wenn ja fragt sich dann nur noch, wie ich den Waveheader dann jedesmal zurückkomplettiere, um es mal so auszudrücken ^^


Delphi-Quellcode:
(******************************************************************************)
(*                             CallBack-Routine                               *)
(******************************************************************************)
  (* Callback WaveStream *)
  function RecordingCallback(Handle: HRECORD; buffer: Pointer; length, user: DWord): boolean; stdcall;
    begin
        // Kopiere neuen Bufferinhalt in den Memory Buffer
       Formular.WaveStream.Write(buffer^, length);
        // Weiteres Aufnehmen erlauben
       Result := True;

    end; // function Callback

  (* Callback InsertStream *)
  function RecordingInsertCallback(Handle: HRECORD; buffer: Pointer; length, user: DWord): boolean; stdcall;
    begin
        // Kopiere neuen Bufferinhalt in den Memory Buffer
       Formular.InsertStream.Write(buffer^, length);
        // Weiteres Aufnehmen erlauben
       Result := True;

    end;


(******************************************************************************)
(*                          Start und Stop Aufnahme                           *)
(******************************************************************************)
  (* Aufnahme Start *)
  procedure TFormular.StartRecording;
    var
      vol: Float;
      i: Integer;
      Flag: DWord;
    begin
      InsertRec := False;

      vol := RecordPegelBar.Position/100;
      while BASS_RecordSetInput(i, BASS_INPUT_OFF, vol)
        do i := i + 1;

      if WaveStream.Size = 0 then
        begin
           // Header für WAV-File generieren

           with WaveHdr do
            begin
                riff := 'RIFF';
                len := 36;
                cWavFmt := 'WAVEfmt ';
                dwHdrLen := 16;
                wFormat := 1;
                wNumChannels := 2;
                dwSampleRate := 44100;
                wBlockAlign := 4;
                dwBytesPerSec := 176400;
                wBitsPerSample := 16;
                cData := 'data';
                dwDataLen := 0;
            end; // with

           WaveStream.Write(WaveHdr, SizeOf(WAVHDR));
           i := 0;

            // ---LoWord-- ----HiWord----
          Flag := MakeLong(c16BitAudio, cRecordingTime);
           // Aufnahmebeginn @ 44100hz 16-bit stereo
           rchan := BASS_RecordStart(cSamplerate,
                                    cNumChannels,
                                    Flag,
                                    @RecordingCallback,
                                    nil);
        end
      else
        begin
          InsertRec := True;

          if Rec_Overwrite.Checked = True then
            begin
              try
                InsertPos := GetPos;
                InsertStream := TMemoryStream.Create;

                  // ---LoWord-- ----HiWord----
                Flag := MakeLong(c16BitAudio, cRecordingTime);
                   // Aufnahmebeginn @ 44100hz 16-bit stereo
                 rchan := BASS_RecordStart(cSamplerate,
                                          cNumChannels,
                                          Flag,
                                          @RecordingInsertCallback,
                                          nil);
              except
                InsertStream.Free;
              end; // try
            end; // if

          if Rec_Passage.Checked = True then
            begin
                // hier an aktueller Position Passage einfügen
            end; // if
        end; // if

         if rchan = 0
          then begin
              MessageDlg('Aufnahme konnte nicht gestartet werden!',
                        mtError, [mbOk], 0);
              WaveStream.Clear;
           end;
    end; // procedure StartRecording

  (* Stop recording *)
  procedure TFormular.StopRecording;
    var
       i: integer;
    begin
       BASS_ChannelStop(rchan);

      if InsertRec = True then
        begin
          if Rec_Overwrite.Checked = True then
            begin
                // hier Streams zusammenfügen /nach aktueller Posi fortfahren
              try
                BufStream := TMemoryStream.Create;
                BufStream2.Seek(0, soFromBeginning);
                BufStream.Write(BufStream2.Memory^, InsertPos);
                BufStream.Write(InsertStream.Memory^, InsertStream.Size);
                //BufStream.Write(PByteArray(WaveStream.Memory)^[InsertPos],WaveStream.Size-InsertPos);
                WaveStream.SetSize(BufStream.Size);
                Move(BufStream.Memory^, WaveStream.Memory^, BufStream.Size);
              finally
                FreeAndNil(BufStream);
                FreeAndNil(BufStream2);
                FreeAndNil(InsertStream);
              end; // try
          end; // if

          if Rec_Passage.Checked = True then
            begin
                // hier BufStream nach neuer Passage anfügen
          end; // if
      end; // if

      try
        BufStream2 := TMemoryStream.Create;
        BufStream2.CopyFrom(WaveStream, 0);
      except
        FreeAndNil(BufStream2);
      end; // try

         // WAV-Header komplettieren
       WaveStream.Position := 4;
       i := WaveStream.Size - 8;
       WaveStream.Write(i, 4);
       i := i - $24;
       WaveStream.Position := 40;
       WaveStream.Write(i, 4);
       WaveStream.Position := 0;

         // Stream für aufgenomme Daten kreieren
       chan := BASS_StreamCreateFile(True, WaveStream.Memory, 0, WaveStream.Size, 0);


       if chan <> 0
        then begin
          //???
         end
      else begin
          MessageDlg('Fehler beim Erstellen eines Streams aus der Aufnahme!',
                    mtError, [mbOk], 0);
        end; // if
    end; // procedure StopRecording
Edit2:
An folgenden Sachen liegt es denk ich mal nich, aber der Vollständigkeit halber will ich sie trotzdem ma noch reinstellen.

Delphi-Quellcode:
  (* Update der Progressbar *)
  procedure TFormular.RecordTimerTimer(Sender: TObject);
    var t, t2: integer;
    begin
      ProgressBar.OnChange := nil;
      ProgressBar.Position := Round((BASS_ChannelGetPosition(chan, BASS_POS_BYTE) / BASS_ChannelGetLength(chan, BASS_POS_BYTE)) * 100);
      ProgressBar.OnChange := ProgressBarChange;

      if (chan <> 0) then
        begin
          t := Round(BASS_ChannelBytes2Seconds(chan,
                    BASS_ChannelGetPosition(chan, BASS_POS_BYTE)));
          t2 := Round(BASS_ChannelBytes2Seconds(chan,
                    BASS_ChannelGetLength(chan, BASS_POS_BYTE)));
        progresstimeLabel.Caption := Format('%.2d:%.2d',[t Div 60, t Mod 60]);
        completetimeLabel.Caption := Format('%.2d:%.2d',[t2 Div 60, t2 Mod 60]);
        end;

    end; // procedure RecordTimerTimer

  (* Position via ProgressBar ändern *)
  procedure TFormular.ProgressBarChange(Sender: TObject);
  var Bool: Boolean;
  begin
    Bool := BASS_ChannelIsActive(chan) = BASS_ACTIVE_Playing;

    if Bool then BASS_ChannelPause(chan);

    BASS_ChannelSetPosition(chan, ProgressBar.Position
    * BASS_ChannelGetLength(chan, BASS_POS_BYTE) div 100, BASS_POS_BYTE);

    if Bool then BASS_ChannelPlay(chan, False);

  end; // procedure ProgressBarChange

  (* Position des Chans ermitteln *)
  function TFormular.GetPos: Integer;
    begin
      Result := Round((ProgressBar.Position
                      * BASS_ChannelGetLength(chan, BASS_POS_BYTE)) / 100);
    end; // function GetPos
Franz
  Mit Zitat antworten Zitat
riko.delphipraxis

Registriert seit: 13. Aug 2008
12 Beiträge
 
#16

Re: "bass.dll" Aufnahme an beliebiger Stelle im St

  Alt 11. Sep 2008, 20:48
Der Sinn von BufStream2 erschliesst sich mir nicht...

Wenn du der Meinung bist das dein "rauschen" an der Aufnahme mit dem Wavestream liegt, wieso nimmst du dann nicht einen Stream zum "recorden" und den anderen für dein Ergebnis.

So hast du nur eine Callback und immer einen leeren Stream zum aufnehmen.Bei Aufnahmeende kannst du mit den Recordingdaten machen was du willst...anhängen, einfügen, ...

Und danach korrigierst du den Waveheader im Ergebnis-Stream.
  Mit Zitat antworten Zitat
Ducksoul

Registriert seit: 19. Apr 2006
Ort: Ilmenau
87 Beiträge
 
RAD-Studio 2009 Pro
 
#17

Re: "bass.dll" Aufnahme an beliebiger Stelle im St

  Alt 11. Sep 2008, 21:09
Also das mit dem BufStream2 war nur ein Test in meiner Not. Inzwischen habe ich das auch schon wieder geändert.

Ob das Rauschen am WaveStream liegt weiß ich nich genau, da ich den Fehler nicht eingrenzen kann, aber das muss es ja sein. Ich hoffe, dass dein Tipp mich jetzt weiterbringt, aber große Hoffnung hab ich nicht mehr.

Und morgen muss ich eigentlich fertig werden mit dem Projekt... Oh man... ^^

MfG
Franz
  Mit Zitat antworten Zitat
Ducksoul

Registriert seit: 19. Apr 2006
Ort: Ilmenau
87 Beiträge
 
RAD-Studio 2009 Pro
 
#18

Re: "bass.dll" Aufnahme an beliebiger Stelle im St

  Alt 7. Okt 2008, 18:20
Nabend,
ich muss mich leider nochmal melden. Ich weiß einfach nicht woran der Fehler liegen kann. Falls interesse besteht würde ich auch mal den kompletten Source an jemanden schicken, falls das einer mal testen möchte... Das Programm muss diese Woche fertig werden und ich bekomm einfach den Fehler nicht in den Griff....

Hier der aktuelle Code:

Delphi-Quellcode:
  (* Callback RecStream *)
  function RecordingCallback(Handle: HRECORD; buffer: Pointer; length, user: DWord): boolean; stdcall;
    begin
        // Kopiere neuen Bufferinhalt in den Memory Buffer
      Formular.RecStream.Write(buffer^, length);
        // Weiteres Aufnehmen erlauben
      Result := True;
    end; // function Callback WaveStream
(******************************************************************************)

  (* Aufnahme Beginnen *)
  procedure TFormular.StartRecording;
    var
      i: Integer;
      Flag: DWord;
    begin
      InsertPos := Round((ProgressBar.Position
                      * BASS_ChannelGetLength(chan, BASS_POS_BYTE)) / 100);;

      RecStream := TMemoryStream.Create;
          // ---LoWord-- ----HiWord----
      Flag := MakeLong(c16BitAudio, cRecordingTime);
          // Aufnahmebeginn @ 44100hz 16-bit stereo
      rchan := BASS_RecordStart(cSamplerate,
                                cNumChannels,
                                Flag,
                                @RecordingCallback,
                                nil);


        // Prüfen, ob Aufnahme erfolgreich gestartet
      if rchan = 0
        then begin
          MessageDlg('Aufnahme konnte nicht gestartet werden!',
                      mtError, [mbOk], 0);
          RecStream.Clear;
      end; // if rchan = 0
    end; // procedure StartRecording
(******************************************************************************)

  (* Aufnahme Beenden *)
  procedure TFormular.StopRecording;
    var
       i: integer;
       HeaderStream, InsertBufStream: TMemoryStream;
    begin
          // Aufnahmekanal stoppen
      BASS_ChannelStop(rchan);
      try
              // Header für WAV-File generieren
          with WaveHdr do
            begin
              wNumChannels := 1;
              wBitsPerSample := 16;
              wBlockAlign := wNumChannels * (wBitsPerSample div 8);
              dwSampleRate := 44100;
              dwBytesPerSec := dwSampleRate * wBlockAlign;
              riff := 'RIFF';
              len := 36;
              cWavFmt := 'WAVEfmt ';
              dwHdrLen := 16;
              wFormat := 1;
              cData := 'data';
              dwDataLen := 0;
            end; // with

              // Header in Aufnahmestream schreiben
          HeaderStream := TMemoryStream.Create;
          HeaderStream.Write(WaveHdr, SizeOf(WAVHDR));
          i := 0;

          if WaveStream.Size = 0 then
            begin
                  // Aufnahme ohne Header zwischenspeichern
              BufStream := TMemoryStream.Create;
              RecStream.Seek(0, soFromBeginning);
              BufStream.Write(RecStream.Memory^, RecStream.Size);

              WaveStream.Write(HeaderStream.Memory^, HeaderStream.Size);
              WaveStream.Write(RecStream.Memory^, RecStream.Size);
            end
          else
            begin
              InsertBufStream := TMemoryStream.Create;
              BufStream.Seek(0, soFromBeginning);
              InsertBufStream.Write(HeaderStream.Memory^, HeaderStream.Size);
              InsertBufStream.Write(BufStream.Memory^, InsertPos-HeaderStream.Size);
              InsertBufStream.Write(RecStream.Memory^, RecStream.Size);
              WaveStream.SetSize(InsertBufStream.Size);
              Move(InsertBufStream.Memory^, WaveStream.Memory^
                    , InsertBufStream.Size);

              Edit1.Text := IntToStr(InsertPos);

              BufStream.SetSize(InsertBufStream.Size - HeaderStream.Size);
              InsertBufStream.Seek(HeaderStream.Size, soFromBeginning);
              BufStream.Write(InsertBufStream.Memory^, InsertBufStream.Size - HeaderStream.Size);

              InsertBufStream.Free;
            end;

          (*    if Rec_Overwrite.Checked = True then
                begin
                    // hier Streams zusammenfügen /nach aktueller Posi fortfahren
                  try
                    BufStream := TMemoryStream.Create;
                    BufStream.CopyFrom(WaveStream, InsertPos);
                    BufStream.CopyFrom(RecStream,0);
                    WaveStream.Position := 0;
                    WaveStream.CopyFrom(BufStream, 0);
                  finally
                    FreeAndNil(BufStream);
                  end;  // try
              end;  // if Rec_Overwrite.Checked *)

        finally
          RecStream.Free;
          HeaderStream.Free;
        end;

          (*if Rec_Passage.Checked = True then
            begin
                // hier BufStream nach neuer Passage anfügen
              try
                BufStream := TMemoryStream.Create;
                BufStream.Write(WaveStream.Memory^, InsertPos);
                BufStream.Write(InsertStream.Memory^, InsertStream.Size);
                BufStream.Write(PByteArray(WaveStream.Memory)^[InsertPos],WaveStream.Size-InsertPos);
                WaveStream.SetSize(BufStream.Size);
                Move(BufStream.Memory^, WaveStream.Memory^, BufStream.Size);
              finally
                FreeAndNil(BufStream);
                FreeAndNil(InsertStream);
              end;  // try
          end;  // if Rec_Passage.Checked
      end;  // if InsertRec *)


          // WAV-Header komplettieren
      WaveStream.Position := 4;
      i := WaveStream.Size - 8;
      WaveStream.Write(i, 4);
      i := i - $24;
      WaveStream.Position := 40;
      WaveStream.Write(i, 4);
      WaveStream.Position := 0;

          // Wiedergabestream kreieren
      chan := BASS_StreamCreateFile(True, WaveStream.Memory, 0, WaveStream.Size, 0);

          // Prüfen, ob Wiedergabestream erfolgreich erstellt
      if chan = 0
        then
          MessageDlg('Fehler beim Erstellen eines Streams aus der Aufnahme!',
                      mtError, [mbOk], 0);
    end; // procedure StopRecording

Viele Grüße
Franz
  Mit Zitat antworten Zitat
Ducksoul

Registriert seit: 19. Apr 2006
Ort: Ilmenau
87 Beiträge
 
RAD-Studio 2009 Pro
 
#19

Re: "bass.dll" Aufnahme an beliebiger Stelle im St

  Alt 10. Okt 2008, 13:01
Also kann mir keiner mit dem Problem helfen, oder zumindest ahnen woran der Fehler jetzt liegt?
Franz
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 15:49 Uhr.
Powered by vBulletin® Copyright ©2000 - 2022, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf