AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi Stille aus Wave-Dateien entfernen?

Stille aus Wave-Dateien entfernen?

Ein Thema von Marco Steinebach · begonnen am 17. Jun 2009 · letzter Beitrag vom 14. Aug 2009
Antwort Antwort
Seite 1 von 2  1 2   
Marco Steinebach

Registriert seit: 4. Aug 2006
491 Beiträge
 
Delphi 5 Enterprise
 
#1

Stille aus Wave-Dateien entfernen?

  Alt 17. Jun 2009, 22:46
Hallo Zusammen,
ich bräuchte mal ein paar Tips wie ich es anstellen kann, eine Wave-Datei zu trimmen, will heißen, stille, am Anfang und Ende einer Wave-Datei rauszuschneiden. Das muß nicht supergenau sein, mir geht es um folgendes: Mein Benutzer drückt den Startknopf, sabbelt was ins Mikrophon, rappelt noch ein wenig, und drückt dann stopp. Das ergebnis soll eine Wave mit möglichst nur seinem gesabbel werden.
Meine Fragen:
Wie kann ich den Anfang bzw. das Ende einer Wave abschneiden? (gern mit BASS)
Wie kriege ich raus, ab wo das "gesabbel" anfängt und wo es aufhört? Mit der Lautsträrke, klar, aber ich find die Funktion ums verrecken nicht. *grummel!
Für Tips wäre ich sehr dankbar!
Einen freundlichen Gru´ß
Marco
Marco Steinebach
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#2

Re: Stille aus Wave-Dateien entfernen?

  Alt 17. Jun 2009, 22:59
stille ist eigentlich nur ein geringer Ausschlag. Du müsstest also nur alles Samples vom Anfang an durchgehen und schauen ab wann ein Sample den von dir definierten Minimalausschlag überschreitet.
Ich würde dazu einfach die Datei mit einem TStream (TFileStream) öffnen und dann entsprechend dem Header bis zu den WaveDaten navigieren. Dort Sample für Sample lesen und schauen wie groß der Ausschlag ist.
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
Marco Steinebach

Registriert seit: 4. Aug 2006
491 Beiträge
 
Delphi 5 Enterprise
 
#3

Re: Stille aus Wave-Dateien entfernen?

  Alt 18. Jun 2009, 06:00
Zitat von SirThornberry:
Ich würde dazu einfach die Datei mit einem TStream (TFileStream) öffnen und dann entsprechend dem Header bis zu den WaveDaten navigieren. Dort Sample für Sample lesen und schauen wie groß der Ausschlag ist.
Ja genau, okay, hinter den Header komm ich, , aber woran sieht man, bei dem zahlensalat der dann folgt, wie groß der Ausschlag eines samples ist? Mir ist überhaupt nicht klar, wie ich aus den Wave-Daten was auslesen kann.
Dazu bräuchte ich bitte nochmal einen tip!
Viele Grüße
Marco
Marco Steinebach
  Mit Zitat antworten Zitat
Florian H

Registriert seit: 30. Mär 2003
Ort: Mühlacker
1.043 Beiträge
 
Delphi 6 Professional
 
#4

Re: Stille aus Wave-Dateien entfernen?

  Alt 18. Jun 2009, 08:11
Du könntest eine FFT machen (mit BASS, Beispiele dazu gibts ja hundertfach hier im Forum) und dann den Ausschlag in verschiedenen Frequenzen Sample für Sample messen, bis eben eine Grenze überschritten wird. Dabei kannst du ja verwenden, dass gesprochene Sprache meist andere Frequenzen nutzt, als Umgebungsgeräusche oder das "rumgerappeln". Kannst du ja dann testen und entsprechend gewichten
Florian Heft
  Mit Zitat antworten Zitat
Wishmaster

Registriert seit: 14. Sep 2002
Ort: Steinbach, MB, Canada
301 Beiträge
 
Delphi XE2 Architect
 
#5

Re: Stille aus Wave-Dateien entfernen?

  Alt 19. Jun 2009, 11:32
Hi


Delphi-Quellcode:
function Channel_Get_SilenceLength_16Bit(FileName : String; Pinpoint : Boolean; Threshold : QWORD; var StartPoint, EndPoint : DWORD) : Bool; stdcall;
var
  a, b: Integer;
  pos, count, chan: DWORD;
  buf16: array[0..50000] of Smallint; // 100% OK.
  flag : DWORD;
begin
   result:= false;
   count := 0;
   flag:= BASS_STREAM_DECODE; //BASS_STREAM_DECODE or BASS_STREAM_AUTOFREE

     if Pinpoint then
       flag:= flag or BASS_STREAM_PRESCAN;

     Chan:= BASS_StreamCreateFile(FALSE, PChar(FileName), 0, 0, Flag);
  if Chan = 0 then
     Chan:= BASS_MusicLoad(False, PChar(FileName), 0, 0, Flag or BASS_MUSIC_NOSAMPLE, 0);
  if Chan = 0 then
   Exit;

  while Bass_ChannelIsActive(Chan) <> 0 do
   begin
    b := BASS_ChannelGetData(Chan, @buf16, 20000);
    b := b div 2;
    a := 0;
    while (a < b) and (Abs(buf16[a]) <= Threshold) do
      a := a + 1;
      count := count + (a * 2);
    if (a < b) then
     begin
      while (a <> 0) and (Abs(buf16[a]) > (Threshold div 4)) do
       begin
        a := a - 1;
        count := count - 2;
      end;
      Break;
    end;
  end;
   StartPoint := count; // Start-Point ready

   pos := BASS_ChannelGetLength(Chan);
  while (pos > count) do
   begin
    if pos < 100000 then
      pos := 0
    else
      pos := pos - 100000;
    BASS_ChannelSetPosition(chan, pos);
    b := BASS_ChannelGetData(chan, @buf16, 100000);
    b := b div 2;
    a := b;
   while (a > 0) and (Abs(buf16[a - 1]) <= (Threshold div 2)) do
       a := a - 1;
    if a > 0 then
     begin
      count := pos + (a * 4);
      Break;
     end;
    end;
 EndPoint := Count; // End-Point ready
 BASS_MusicFree(Chan);
 BASS_StreamFree(Chan);
 Result:= true;
end;


function Channel_Get_SilenceLength_32Bit(FileName : String; Pinpoint : Boolean; Threshold : QWORD; var StartPoint, EndPoint : DWORD) : boolean; stdcall;
var
  a, b: Integer;
  pos, count, chan: DWORD;
  buf32: array[0..50000] of Float; //Single
  flag : DWORD;
begin
   Result:= false;

   Flag:= BASS_STREAM_DECODE or BASS_SAMPLE_FLOAT;

  if Pinpoint then
   Flag:= Flag or BASS_STREAM_PRESCAN;


     Chan:= (BASS_StreamCreateFile(FALSE, PChar(FileName), 0, 0, Flag));
  if Chan = 0 then
     Chan:= BASS_MusicLoad(False, PChar(FileName), 0, 0, Flag or BASS_MUSIC_NOSAMPLE, 0);
  if Chan = 0 then
    Exit;

    count := 0;
  while Bass_ChannelIsActive(chan) <> 0 do
   begin
    b := BASS_ChannelGetData(chan, @buf32, 20000);
    b := b div 4;
    a := 0;
    while (a < b) and (Abs(buf32[a]) <= (Threshold / 32768)) do
      a := a + 1;
      count := count + (a * 4);
    if (a < b) then
     begin
      while (a <> 0) and (Abs(buf32[a]) > (Trunc(Threshold / 32768) div 4)) do
       begin
        a := a - 1;
        count := count - 2;
       end;
      Break;
     end;
    end;
     StartPoint := count; // Start-Point ready

    pos := BASS_ChannelGetLength(chan);
  while (pos > count) do
   begin
    if pos < 100000 then
      pos := 0
    else
      pos := pos - 100000;
      BASS_ChannelSetPosition(chan, pos);
      b := BASS_ChannelGetData(chan, @buf32, 100000);
      b := b div 4; // 16Bit = 2 | 32Bit = 4
      a := b;
    while (a > 0) and (Abs(buf32[a - 1]) <= (Threshold div 2) / 32768) do
      a := a -1;
    if a > 0 then
     begin
      count := pos + (a * 8); //8=2
      Break;
    end;
  end;
  EndPoint := Count; // End-Point ready
  BASS_MusicFree(Chan);
  BASS_StreamFree(chan);
  Result:= true;
end;
  Mit Zitat antworten Zitat
Marco Steinebach

Registriert seit: 4. Aug 2006
491 Beiträge
 
Delphi 5 Enterprise
 
#6

Re: Stille aus Wave-Dateien entfernen?

  Alt 20. Jun 2009, 00:16
Hi Wishmaster,
Ganz herzlichen Dank für den Quellcode.
Mein Ansatz war, die Werte mittels BASS_ChannelGetLevel rauszufinden. Allerdings bin ich nicht auf die Idee gekommen, das ganze, für das Ende, rückwärts anzugehen, ich hab einfach mehrere Levels verglichen, und wenn’s 20 mal unterm threshold war, dann war schluß. Da ist deines natürlich um Längen besser.

Ich habe noch ein paar Fragen zum Code:
1. Wofür ist die möglichkeit des PreScan hier sinnvoll?
2. Warum vergleichst du auf Threshold div 2 bzw. threshold div 4?

Die Fragen, weil ich gerne verstehen würde, wie du es gemacht hast.

So, und damit man das Resultat auch als Wave-Datei hat, , hier der Rest des Programms.
Kann man das evtl. noch verbessern?

Delphi-Quellcode:
procedure TMainForm.BStartClick(Sender: TObject);
const
  Buffersize = 1024;
var
  sh: HSTREAM; // sound handle
  eh: HENCODE; // encoder handle
  buf: array of byte;
  Startposition, Endposition: dWord;
begin
  SetLength (buf, BufferSize);
  BASS_init (-1, 44100, 0, application.handle, nil);
  if not Channel_Get_SilenceLength_16Bit ('Test.wav', true, 5000, Startposition, Endposition) then
  begin
    ErrorMsg ('Calculation of silence failed!');
    exit
  end;

  sh := BASS_StreamCreateFile (false, pChar('test.wav'), 0, 0, BASS_Stream_Decode);
  if sh = 0 then
  begin
    ErrorMsg ('Could not open input file.');
    exit
  end;

  BASS_ChannelSetPosition (sh, Startposition, BASS_POS_Byte);
  eh := BASS_Encode_Start (sh, pChar('test_silent.wav'), BASS_Encode_PCM + BASS_Encode_AutoFree, nil, nil);
  if eh = 0 then
  begin
    ErrorMsg ('Encoder not started.');
    BASS_StreamFree (sh);
    exit
  end;
  While BASS_ChannelIsActive (sh) <> BASS_ACTIVE_Stopped do
  begin
    BASS_ChannelGetData (sh, buf, Buffersize);
    if BASS_ChannelGetPosition (sh, BASS_Pos_Byte) >= EndPosition then
      BASS_ChannelStop (sh);
  end;
  BASS_StreamFree (sh);
  Infobox ('Ready!');
end;
Ich hab’s auch schon mittels eine BASS_SYNC_Pos probiert, aber der Sync wird niemals erreicht.

Freundliche Grüße
Marco
Marco Steinebach
  Mit Zitat antworten Zitat
Wishmaster

Registriert seit: 14. Sep 2002
Ort: Steinbach, MB, Canada
301 Beiträge
 
Delphi XE2 Architect
 
#7

Re: Stille aus Wave-Dateien entfernen?

  Alt 20. Jun 2009, 10:46
Hi

ich freue mich das dir der code weiter geholfen hat.

PreScan ist mehr für MP3s gedacht. Benutze es nur wen du das unbedingt brauchst, es dauert en Stück länger um eine mp3 Datei zu Laden.

Aus der bass Hilfe
Zitat:
Enable pin-point accurate seeking (to the exact byte) on the MP3/MP2/MP1 stream. This also increases the time taken to create the stream, due to the entire file being pre-scanned for the seek points.
Tipp
1, wen möglich verwende immer 32 Bit (bessere qualität)
2, ich würde an deiner stelle die bassmix.dll benutzen

in deinem Code würde ich den buffer vergrößern besonders wen du nach wma encodieren willst

Delphi-Quellcode:
var Buff32 : Array [0..20000] of FLOAT; // 32 Bit
  BASS_ChannelGetData(Channel, @Buff32, SizeOf(Buff32));

var Buff16 : Array [0..20000] of LongInt; // 16 Bit
  Result:=BASS_ChannelGetData(Channel, @Buff16, SizeOf(Buff16));
  Mit Zitat antworten Zitat
Marco Steinebach

Registriert seit: 4. Aug 2006
491 Beiträge
 
Delphi 5 Enterprise
 
#8

Re: Stille aus Wave-Dateien entfernen?

  Alt 1. Jul 2009, 18:23
Hallo Wishmaster,
Zitat von Wishmaster:
ich freue mich das dir der code weiter geholfen hat.
Nochmal vielen Dank, hat er wirklich!

Zitat von Wishmaster:
2, ich würde an deiner stelle die bassmix.dll benutzen
wie jetzt, um dann die neue Wave zu speichern? Ähm, wie denn? Ich hab nicht mal 'ne Idee.

Zitat von Wishmaster:
in deinem Code würde ich den buffer vergrößern besonders wen du nach wma encodieren willst
Ich hatte ihn so klein gehalten, da ich möglichst na an die errechnete Endposition heranwollte - und der Trick mit dem eingesetzten SyncPos nicht geklappt hat.

Viele Grüße
Marco
Marco Steinebach
  Mit Zitat antworten Zitat
Wishmaster

Registriert seit: 14. Sep 2002
Ort: Steinbach, MB, Canada
301 Beiträge
 
Delphi XE2 Architect
 
#9

Re: Stille aus Wave-Dateien entfernen?

  Alt 2. Jul 2009, 09:51
Hi

Zitat:
wie jetzt, um dann die neue Wave zu speichern? Ähm, wie denn? Ich hab nicht mal 'ne Idee.
Nein! Mit der bassmix.dll kannst mehrere Dateien zusammen mixen, Samplerate und Channels ändern.
du kannst auch die Lautstärke und Balance ändern

Zitat:
When mixing a channel, the mixer makes use of the channel's freq/volume/pan attributes, as set with BASS_ChannelSetAttribute. The BASS_CONFIG_CURVE_VOL and BASS_CONFIG_CURVE_PAN config option settings are also used.

Zitat:
Ich hatte ihn so klein gehalten, da ich möglichst na an die errechnete Endposition heranwollte - und der Trick mit dem eingesetzten SyncPos nicht geklappt hat.
Das kannst du auch mit der bassmix.dll erreichen!

Delphi-Quellcode:
Procedure Encode(inFile, outFile : String; Samplerate, Bits, Channels : integer) // 44100, 16, 2
Var Channel, Mixer : DWORD;
       Flag, encFlag : DWORD;
       StopTime : INT64;
begin
     Channel:= BASS_StreamCreateFile(FALSE, PChar(inFile), 0, 0, Flag);

     Mixer := BASS_Mixer_StreamCreate(Samplerate, Channels, BASS_SAMPLE_FLOAT or BASS_STREAM_DECODE);

    (*
        limiting the duration to X seconds
        StopTime = The maximum amount of data (in bytes) to mix... 0 = no limit.
    *)


     StopTime := BASS_ChannelSeconds2Bytes(Mixer, 2) ; // in Sec.

     Flag:= BASS_MIXER_LIMIT or BASS_MIXER_FILTER or BASS_MIXER_BUFFER;
     BASS_Mixer_StreamAddChannelEx(Mixer, Channel, Flag, 0, StopTime);

     BASS_ChannelSetPosition (..., Startposition, BASS_POS_Byte);

     encFlag:= 0;
    if Bits = 8 then encFlag:= encFlag or BASS_ENCODE_FP_8BIT;
    if Bits = 16 then encFlag:= encFlag or BASS_ENCODE_FP_16BIT;
    if Bits = 24 then encFlag:= encFlag or BASS_ENCODE_FP_24BIT;
    if Bits = 32 then encFlag:= encFlag or BASS_ENCODE_FP_32BIT;
   // else 32 Bit (floating-point)

     BASS_Encode_Start(..., PChar(outFile), encFlag or BASS_Encode_AutoFree, nil, nil)
  Mit Zitat antworten Zitat
Marco Steinebach

Registriert seit: 4. Aug 2006
491 Beiträge
 
Delphi 5 Enterprise
 
#10

Re: Stille aus Wave-Dateien entfernen?

  Alt 13. Aug 2009, 22:29
Hallo,
Ich hab mir den Code heute nochmal zu gemüte geführt und, denke?, er hat einen Fehler.
Delphi-Quellcode:
function Channel_Get_SilenceLength_16Bit(FileName : String; Pinpoint : Boolean; Threshold : QWORD; var StartPoint, EndPoint : DWORD) : Bool; stdcall;
var
  a, b: Integer;
  pos, count, chan: DWORD;
  buf16: array[0..50000] of Smallint; // 100% OK.
  flag : DWORD;
begin
   result:= false;
   count := 0;
   flag:= BASS_STREAM_DECODE; //BASS_STREAM_DECODE or BASS_STREAM_AUTOFREE

     if Pinpoint then
       flag:= flag or BASS_STREAM_PRESCAN;

     Chan:= BASS_StreamCreateFile(FALSE, PChar(FileName), 0, 0, Flag);
  if Chan = 0 then
     Chan:= BASS_MusicLoad(False, PChar(FileName), 0, 0, Flag or BASS_MUSIC_NOSAMPLE, 0);
  if Chan = 0 then
   Exit;

  while Bass_ChannelIsActive(Chan) <> 0 do
   begin
    b := BASS_ChannelGetData(Chan, @buf16, 20000);
    b := b div 2;
    a := 0;
    while (a < b) and (Abs(buf16[a]) <= Threshold) do
      a := a + 1;
      count := count + (a * 2);
    if (a < b) then
     begin
      while (a <> 0) and (Abs(buf16[a]) > (Threshold div 4)) do
       begin
        a := a - 1;
        count := count - 2;
      end;
      Break;
    end;
  end;
   StartPoint := count; // Start-Point ready

   pos := BASS_ChannelGetLength(Chan);
  while (pos > count) do
   begin
    if pos < 100000 then
      pos := 0
    else
      pos := pos - 100000;
    BASS_ChannelSetPosition(chan, pos);
    b := BASS_ChannelGetData(chan, @buf16, 100000);
// ... so, hier geht's los:
    b := b div 2; // b ist also die Anzahl der samples
    a := b;
   while (a > 0) and (Abs(buf16[a - 1]) <= (Threshold div 2)) do
       a := a - 1;
    if a > 0 then
     begin
      count := pos + (a * 4); // warum 4, müßte doch bei smallint, also 2 byte, * 2 heißen, oder? Break;
     end;
    end;
 EndPoint := Count; // End-Point ready
 BASS_MusicFree(Chan);
 BASS_StreamFree(Chan);
 Result:= true;
end;
Das gleiche gilt, natürlich, auch für die 32-Bit-Variante.
Der Code produziert nämlich manchmal Ergebnisse, deren Endposition größer ist, als die tatsächliche Länge.
Hilf mir mal bitte!
Einen freundlichen Gruß
Marco
Marco Steinebach
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2   

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 10:27 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